filtered = new ArrayList<>();
String sl = s.toLowerCase();
@@ -241,12 +243,14 @@ public SelectList(Skin skin, final TextField inputBox) {
setActor(list);
list.addListener(new ClickListener() {
+ @Override
public void clicked(InputEvent event, float x, float y) {
selectBox.setText(list.getSelected().toString());
selectedIndex = list.getSelectedIndex();
hide();
}
+ @Override
public boolean mouseMoved(InputEvent event, float x, float y) {
list.setSelectedIndex(
Math.min(list.getItems().size - 1, (int) ((list.getHeight() - y) / list.getItemHeight())));
@@ -255,9 +259,10 @@ public boolean mouseMoved(InputEvent event, float x, float y) {
});
addListener(new InputListener() {
+ @Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
if (toActor == null || !isAscendantOf(toActor))
- if(selectedIndex < list.getItems().size)
+ if (selectedIndex < list.getItems().size)
list.setSelectedIndex(selectedIndex);
else
EditorLogger.error("EditableSelectBox:exit selectedIndex outOfBounds: " + selectedIndex);
@@ -265,15 +270,22 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor)
});
hideListener = new InputListener() {
+ @Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
Actor target = event.getTarget();
if (isAscendantOf(target))
return false;
- list.setSelectedIndex(selectedIndex);
+
+ if (selectedIndex < list.getItems().size)
+ list.setSelectedIndex(selectedIndex);
+ else
+ EditorLogger.error("EditableSelectBox:touchDown selectedIndex outOfBounds: " + selectedIndex);
+
hide();
return false;
}
+ @Override
public boolean keyDown(InputEvent event, int keycode) {
if (keycode == Keys.ESCAPE)
hide();
@@ -332,7 +344,6 @@ public void show(Stage stage) {
previousScrollFocus = actor;
stage.setScrollFocus(this);
-
list.setTouchable(Touchable.enabled);
clearActions();
// getColor().a = 0;
@@ -359,6 +370,7 @@ public void hide() {
addAction(sequence(fadeOut(0.15f, Interpolation.fade), Actions.removeActor()));
}
+ @Override
public void draw(Batch batch, float parentAlpha) {
selectBox.localToStageCoordinates(temp.set(0, 0));
if (!temp.equals(screenPosition))
@@ -366,6 +378,7 @@ public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
}
+ @Override
public void act(float delta) {
super.act(delta);
toFront();
diff --git a/adventure-editor/src/main/java/com/bladecoder/engineeditor/ui/panels/FilteredSelectBox.java b/adventure-editor/src/main/java/com/bladecoder/engineeditor/ui/panels/FilteredSelectBox.java
index bbd5dcbb8..e8d45dea0 100644
--- a/adventure-editor/src/main/java/com/bladecoder/engineeditor/ui/panels/FilteredSelectBox.java
+++ b/adventure-editor/src/main/java/com/bladecoder/engineeditor/ui/panels/FilteredSelectBox.java
@@ -39,585 +39,667 @@
import com.badlogic.gdx.utils.Pool;
import com.badlogic.gdx.utils.Pools;
-
-/** A select box (aka a drop-down list) allows a user to choose one of a number of values from a list. When inactive, the selected
- * value is displayed. When activated, it shows the list of values that may be selected.
+/**
+ * A select box (aka a drop-down list) allows a user to choose one of a number
+ * of values from a list. When inactive, the selected value is displayed. When
+ * activated, it shows the list of values that may be selected.
*
* {@link ChangeEvent} is fired when the selectbox selection changes.
*
- * The preferred size of the select box is determined by the maximum text bounds of the items and the size of the
- * {@link FilteredSelectBoxStyle#background}.
+ * The preferred size of the select box is determined by the maximum text bounds
+ * of the items and the size of the {@link FilteredSelectBoxStyle#background}.
+ *
* @author mzechner
* @author Nathan Sweet
* @author Rafael GarcÃa
*/
public class FilteredSelectBox extends Widget implements Disableable {
-
- static final Vector2 temp = new Vector2();
-
- FilteredSelectBoxStyle style;
- final Array items = new Array();
- final ArraySelection selection = new ArraySelection(items);
- SelectBoxList selectBoxList;
- private float prefWidth, prefHeight;
- private ClickListener clickListener;
- boolean disabled;
- private int alignment = Align.left;
-
- public FilteredSelectBox (Skin skin) {
- this(skin.get(FilteredSelectBoxStyle.class));
- }
-
- public FilteredSelectBox (Skin skin, String styleName) {
- this(skin.get(styleName, FilteredSelectBoxStyle.class));
- }
-
- public FilteredSelectBox (FilteredSelectBoxStyle style) {
- setStyle(style);
- setSize(getPrefWidth(), getPrefHeight());
-
- selection.setActor(this);
- selection.setRequired(true);
-
- selectBoxList = new SelectBoxList(this);
-
- addListener(clickListener = new ClickListener() {
- public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
- if (pointer == 0 && button != 0) return false;
- if (disabled) return false;
- if (selectBoxList.hasParent())
- hideList();
- else
- showList();
- return true;
- }
- });
-
- }
-
- /** Set the max number of items to display when the select box is opened. Set to 0 (the default) to display as many as fit in
- * the stage height. */
- public void setMaxListCount (int maxListCount) {
- selectBoxList.maxListCount = maxListCount;
- }
- /** @return Max number of items to display when the box is opened, or <= 0 to display them all. */
- public int getMaxListCount () {
- return selectBoxList.maxListCount;
- }
-
- protected void setStage (Stage stage) {
- if (stage == null) selectBoxList.hide();
- super.setStage(stage);
- }
-
- public void setStyle (FilteredSelectBoxStyle style) {
- if (style == null) throw new IllegalArgumentException("style cannot be null.");
- this.style = style;
- if (selectBoxList != null) {
- selectBoxList.setStyle(style.scrollStyle);
- selectBoxList.list.setStyle(style.listStyle);
+ static final Vector2 temp = new Vector2();
+
+ FilteredSelectBoxStyle style;
+ final Array items = new Array<>();
+ final ArraySelection selection = new ArraySelection<>(items);
+ SelectBoxList selectBoxList;
+ private float prefWidth, prefHeight;
+ private ClickListener clickListener;
+ boolean disabled;
+ private int alignment = Align.left;
+
+ public FilteredSelectBox(Skin skin) {
+ this(skin.get(FilteredSelectBoxStyle.class));
+ }
+
+ public FilteredSelectBox(Skin skin, String styleName) {
+ this(skin.get(styleName, FilteredSelectBoxStyle.class));
+ }
+
+ public FilteredSelectBox(FilteredSelectBoxStyle style) {
+ setStyle(style);
+ setSize(getPrefWidth(), getPrefHeight());
+
+ selection.setActor(this);
+ selection.setRequired(true);
+
+ selectBoxList = new SelectBoxList<>(this);
+
+ addListener(clickListener = new ClickListener() {
+ @Override
+ public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
+ if (pointer == 0 && button != 0)
+ return false;
+ if (disabled)
+ return false;
+ if (selectBoxList.hasParent())
+ hideList();
+ else
+ showList();
+ return true;
}
+ });
+
+ }
+
+ /**
+ * Set the max number of items to display when the select box is opened. Set to
+ * 0 (the default) to display as many as fit in the stage height.
+ */
+ public void setMaxListCount(int maxListCount) {
+ selectBoxList.maxListCount = maxListCount;
+ }
+
+ /**
+ * @return Max number of items to display when the box is opened, or <= 0 to
+ * display them all.
+ */
+ public int getMaxListCount() {
+ return selectBoxList.maxListCount;
+ }
+
+ @Override
+ protected void setStage(Stage stage) {
+ if (stage == null)
+ selectBoxList.hide();
+ super.setStage(stage);
+ }
+
+ public void setStyle(FilteredSelectBoxStyle style) {
+ if (style == null)
+ throw new IllegalArgumentException("style cannot be null.");
+ this.style = style;
+ if (selectBoxList != null) {
+ selectBoxList.setStyle(style.scrollStyle);
+ selectBoxList.list.setStyle(style.listStyle);
+ }
+ invalidateHierarchy();
+ }
+
+ /**
+ * Returns the select box's style. Modifying the returned style may not have an
+ * effect until {@link #setStyle(FilteredSelectBoxStyle)} is called.
+ */
+ public FilteredSelectBoxStyle getStyle() {
+ return style;
+ }
+
+ /**
+ * Set the backing Array that makes up the choices available in the SelectBox
+ */
+ @SuppressWarnings("unchecked")
+ public void setItems(T... newItems) {
+ if (newItems == null)
+ throw new IllegalArgumentException("newItems cannot be null.");
+ float oldPrefWidth = getPrefWidth();
+
+ items.clear();
+ items.addAll(newItems);
+ selection.validate();
+ selectBoxList.list.setItems(items);
+
+ invalidate();
+ if (oldPrefWidth != getPrefWidth())
invalidateHierarchy();
- }
-
- /** Returns the select box's style. Modifying the returned style may not have an effect until {@link #setStyle(FilteredSelectBoxStyle)}
- * is called. */
- public FilteredSelectBoxStyle getStyle () {
- return style;
- }
-
- /** Set the backing Array that makes up the choices available in the SelectBox */
- @SuppressWarnings("unchecked")
- public void setItems (T... newItems) {
- if (newItems == null) throw new IllegalArgumentException("newItems cannot be null.");
- float oldPrefWidth = getPrefWidth();
+ }
- items.clear();
- items.addAll(newItems);
- selection.validate();
- selectBoxList.list.setItems(items);
+ /** Sets the items visible in the select box. */
+ public void setItems(Array newItems) {
+ if (newItems == null)
+ throw new IllegalArgumentException("newItems cannot be null.");
+ float oldPrefWidth = getPrefWidth();
- invalidate();
- if (oldPrefWidth != getPrefWidth()) invalidateHierarchy();
- }
+ items.clear();
+ items.addAll(newItems);
+ selection.validate();
+ selectBoxList.list.setItems(items);
- /** Sets the items visible in the select box. */
- public void setItems (Array newItems) {
- if (newItems == null) throw new IllegalArgumentException("newItems cannot be null.");
- float oldPrefWidth = getPrefWidth();
-
- items.clear();
- items.addAll(newItems);
- selection.validate();
- selectBoxList.list.setItems(items);
-
- invalidate();
- if (oldPrefWidth != getPrefWidth()) invalidateHierarchy();
- }
-
- public void clearItems () {
- if (items.size == 0) return;
- items.clear();
- selection.clear();
+ invalidate();
+ if (oldPrefWidth != getPrefWidth())
invalidateHierarchy();
- }
-
- /** Returns the internal items array. If modified, {@link #setItems(Array)} must be called to reflect the changes. */
- public Array getItems () {
- return items;
- }
-
- @Override
- public void layout () {
- Drawable bg = style.background;
- BitmapFont font = style.font;
-
- if (bg != null) {
- prefHeight = Math.max(bg.getTopHeight() + bg.getBottomHeight() + font.getCapHeight() - font.getDescent() * 2,
+ }
+
+ public void clearItems() {
+ if (items.size == 0)
+ return;
+ items.clear();
+ selection.clear();
+ invalidateHierarchy();
+ }
+
+ /**
+ * Returns the internal items array. If modified, {@link #setItems(Array)} must
+ * be called to reflect the changes.
+ */
+ public Array getItems() {
+ return items;
+ }
+
+ @Override
+ public void layout() {
+ Drawable bg = style.background;
+ BitmapFont font = style.font;
+
+ if (bg != null) {
+ prefHeight = Math.max(
+ bg.getTopHeight() + bg.getBottomHeight() + font.getCapHeight() - font.getDescent() * 2,
bg.getMinHeight());
- } else
- prefHeight = font.getCapHeight() - font.getDescent() * 2;
-
- float maxItemWidth = 0;
- Pool layoutPool = Pools.get(GlyphLayout.class);
- GlyphLayout layout = layoutPool.obtain();
- for (int i = 0; i < items.size; i++) {
- layout.setText(font, toString(items.get(i)));
- maxItemWidth = Math.max(layout.width, maxItemWidth);
- }
- layoutPool.free(layout);
-
- prefWidth = maxItemWidth;
- if (bg != null) prefWidth += bg.getLeftWidth() + bg.getRightWidth();
-
- ListStyle listStyle = style.listStyle;
- ScrollPaneStyle scrollStyle = style.scrollStyle;
- float listWidth = maxItemWidth + listStyle.selection.getLeftWidth() + listStyle.selection.getRightWidth();
- if (scrollStyle.background != null)
- listWidth += scrollStyle.background.getLeftWidth() + scrollStyle.background.getRightWidth();
- if (selectBoxList == null || !selectBoxList.isScrollingDisabledY())
- listWidth += Math.max(style.scrollStyle.vScroll != null ? style.scrollStyle.vScroll.getMinWidth() : 0,
+ } else
+ prefHeight = font.getCapHeight() - font.getDescent() * 2;
+
+ float maxItemWidth = 0;
+ Pool layoutPool = Pools.get(GlyphLayout.class);
+ GlyphLayout layout = layoutPool.obtain();
+ for (int i = 0; i < items.size; i++) {
+ layout.setText(font, toString(items.get(i)));
+ maxItemWidth = Math.max(layout.width, maxItemWidth);
+ }
+ layoutPool.free(layout);
+
+ prefWidth = maxItemWidth;
+ if (bg != null)
+ prefWidth += bg.getLeftWidth() + bg.getRightWidth();
+
+ ListStyle listStyle = style.listStyle;
+ ScrollPaneStyle scrollStyle = style.scrollStyle;
+ float listWidth = maxItemWidth + listStyle.selection.getLeftWidth() + listStyle.selection.getRightWidth();
+ if (scrollStyle.background != null)
+ listWidth += scrollStyle.background.getLeftWidth() + scrollStyle.background.getRightWidth();
+ if (selectBoxList == null || !selectBoxList.isScrollingDisabledY())
+ listWidth += Math.max(style.scrollStyle.vScroll != null ? style.scrollStyle.vScroll.getMinWidth() : 0,
style.scrollStyle.vScrollKnob != null ? style.scrollStyle.vScrollKnob.getMinWidth() : 0);
- prefWidth = Math.max(prefWidth, listWidth);
- }
-
- @Override
- public void draw (Batch batch, float parentAlpha) {
- validate();
-
- Drawable background;
- if (disabled && style.backgroundDisabled != null)
- background = style.backgroundDisabled;
- else if (selectBoxList.hasParent() && style.backgroundOpen != null)
- background = style.backgroundOpen;
- else if (clickListener.isOver() && style.backgroundOver != null)
- background = style.backgroundOver;
- else if (style.background != null)
- background = style.background;
- else
- background = null;
- BitmapFont font = style.font;
- Color fontColor = (disabled && style.disabledFontColor != null) ? style.disabledFontColor : style.fontColor;
-
- Color color = getColor();
- float x = getX(), y = getY();
- float width = getWidth(), height = getHeight();
-
- batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
- if (background != null) background.draw(batch, x, y, width, height);
-
- T selected = selection.first();
- if (selected != null) {
- if (background != null) {
- width -= background.getLeftWidth() + background.getRightWidth();
- height -= background.getBottomHeight() + background.getTopHeight();
- x += background.getLeftWidth();
- y += (int)(height / 2 + background.getBottomHeight() + font.getData().capHeight / 2);
- } else {
- y += (int)(height / 2 + font.getData().capHeight / 2);
- }
- font.setColor(fontColor.r, fontColor.g, fontColor.b, fontColor.a * parentAlpha);
- drawItem(batch, font, selected, x, y, width);
+ prefWidth = Math.max(prefWidth, listWidth);
+ }
+
+ @Override
+ public void draw(Batch batch, float parentAlpha) {
+ validate();
+
+ Drawable background;
+ if (disabled && style.backgroundDisabled != null)
+ background = style.backgroundDisabled;
+ else if (selectBoxList.hasParent() && style.backgroundOpen != null)
+ background = style.backgroundOpen;
+ else if (clickListener.isOver() && style.backgroundOver != null)
+ background = style.backgroundOver;
+ else if (style.background != null)
+ background = style.background;
+ else
+ background = null;
+ BitmapFont font = style.font;
+ Color fontColor = (disabled && style.disabledFontColor != null) ? style.disabledFontColor : style.fontColor;
+
+ Color color = getColor();
+ float x = getX(), y = getY();
+ float width = getWidth(), height = getHeight();
+
+ batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
+ if (background != null)
+ background.draw(batch, x, y, width, height);
+
+ T selected = selection.first();
+ if (selected != null) {
+ if (background != null) {
+ width -= background.getLeftWidth() + background.getRightWidth();
+ height -= background.getBottomHeight() + background.getTopHeight();
+ x += background.getLeftWidth();
+ y += (int) (height / 2 + background.getBottomHeight() + font.getData().capHeight / 2);
+ } else {
+ y += (int) (height / 2 + font.getData().capHeight / 2);
}
- }
-
- protected GlyphLayout drawItem (Batch batch, BitmapFont font, T item, float x, float y, float width) {
- String string = toString(item);
- return font.draw(batch, string, x, y, 0, string.length(), width, alignment, false, "...");
- }
-
- /** Sets the alignment of the selected item in the select box. See {@link #getList()} and {@link List#setAlignment(int)} to set
- * the alignment in the list shown when the select box is open.
- * @param alignment See {@link Align}. */
- public void setAlignment (int alignment) {
- this.alignment = alignment;
- }
-
- /** Get the set of selected items, useful when multiple items are selected
- * @return a Selection object containing the selected elements */
- public ArraySelection getSelection () {
- return selection;
- }
-
- /** Returns the first selected item, or null. For multiple selections use {@link SelectBox#getSelection()}. */
- public T getSelected () {
- return selection.first();
- }
-
- /** Sets the selection to only the passed item, if it is a possible choice, else selects the first item. */
- public void setSelected (T item) {
+ font.setColor(fontColor.r, fontColor.g, fontColor.b, fontColor.a * parentAlpha);
+ drawItem(batch, font, selected, x, y, width);
+ }
+ }
+
+ protected GlyphLayout drawItem(Batch batch, BitmapFont font, T item, float x, float y, float width) {
+ String string = toString(item);
+ return font.draw(batch, string, x, y, 0, string.length(), width, alignment, false, "...");
+ }
+
+ /**
+ * Sets the alignment of the selected item in the select box. See
+ * {@link #getList()} and {@link List#setAlignment(int)} to set the alignment in
+ * the list shown when the select box is open.
+ *
+ * @param alignment See {@link Align}.
+ */
+ public void setAlignment(int alignment) {
+ this.alignment = alignment;
+ }
+
+ /**
+ * Get the set of selected items, useful when multiple items are selected
+ *
+ * @return a Selection object containing the selected elements
+ */
+ public ArraySelection getSelection() {
+ return selection;
+ }
+
+ /**
+ * Returns the first selected item, or null. For multiple selections use
+ * {@link SelectBox#getSelection()}.
+ */
+ public T getSelected() {
+ return selection.first();
+ }
+
+ /**
+ * Sets the selection to only the passed item, if it is a possible choice, else
+ * selects the first item.
+ */
+ public void setSelected(T item) {
// T item = (T)i;
- if (items.contains(item, false))
- selection.set(item);
- else if (items.size > 0)
- selection.set(items.first());
- else
- selection.clear();
- }
-
- /** @return The index of the first selected item. The top item has an index of 0. Nothing selected has an index of -1. */
- public int getSelectedIndex () {
- ObjectSet selected = selection.items();
- return selected.size == 0 ? -1 : items.indexOf(selected.first(), false);
- }
-
- /** Sets the selection to only the selected index. */
- public void setSelectedIndex (int index) {
- selection.set(items.get(index));
- }
-
- public void setDisabled (boolean disabled) {
- if (disabled && !this.disabled) hideList();
- this.disabled = disabled;
- }
-
- public boolean isDisabled () {
- return disabled;
- }
-
- public float getPrefWidth () {
- validate();
- return prefWidth;
- }
-
- public float getPrefHeight () {
- validate();
- return prefHeight;
- }
+ if (items.contains(item, false))
+ selection.set(item);
+ else if (items.size > 0)
+ selection.set(items.first());
+ else
+ selection.clear();
+ }
+
+ /**
+ * @return The index of the first selected item. The top item has an index of 0.
+ * Nothing selected has an index of -1.
+ */
+ public int getSelectedIndex() {
+ ObjectSet selected = selection.items();
+ return selected.size == 0 ? -1 : items.indexOf(selected.first(), false);
+ }
+
+ /** Sets the selection to only the selected index. */
+ public void setSelectedIndex(int index) {
+ selection.set(items.get(index));
+ }
+
+ @Override
+ public void setDisabled(boolean disabled) {
+ if (disabled && !this.disabled)
+ hideList();
+ this.disabled = disabled;
+ }
+
+ @Override
+ public boolean isDisabled() {
+ return disabled;
+ }
+
+ @Override
+ public float getPrefWidth() {
+ validate();
+ return prefWidth;
+ }
+
+ @Override
+ public float getPrefHeight() {
+ validate();
+ return prefHeight;
+ }
+
+ protected String toString(T item) {
+ return item.toString();
+ }
+
+ public void showList() {
+ if (items.size == 0)
+ return;
+ selectBoxList.show(getStage());
+ }
+
+ public void hideList() {
+ selectBoxList.hide();
+ }
+
+ /** Returns the list shown when the select box is open. */
+ public List getList() {
+ return selectBoxList.list;
+ }
+
+ /** Disables scrolling of the list shown when the select box is open. */
+ public void setScrollingDisabled(boolean y) {
+ selectBoxList.setScrollingDisabled(true, y);
+ invalidateHierarchy();
+ }
+
+ /**
+ * Returns the scroll pane containing the list that is shown when the select box
+ * is open.
+ */
+ public ScrollPane getScrollPane() {
+ return selectBoxList;
+ }
+
+ protected void onShow(Actor selectBoxList, boolean below) {
+ selectBoxList.getColor().a = 0;
+ selectBoxList.addAction(fadeIn(0.3f, Interpolation.fade));
+ }
+
+ protected void onHide(Actor selectBoxList) {
+ selectBoxList.getColor().a = 1;
+ selectBoxList.addAction(sequence(fadeOut(0.15f, Interpolation.fade), removeActor()));
+ }
+
+ /** @author Nathan Sweet */
+ final class SelectBoxList extends ScrollPane {
+ private final FilteredSelectBox selectBox;
+ int maxListCount;
+ private final Vector2 screenPosition = new Vector2();
+ final List list;
+ private InputListener hideListener;
+ private Actor previousScrollFocus;
+ private TextField filterField;
+
+ public SelectBoxList(final FilteredSelectBox selectBox) {
+ super(null, selectBox.style.scrollStyle);
+ this.selectBox = selectBox;
+
+ setOverscroll(false, false);
+ setFadeScrollBars(false);
+ setScrollingDisabled(true, false);
+
+ list = new List(selectBox.style.listStyle) {
+ @Override
+ public String toString(T obj) {
+ return selectBox.toString(obj);
+ }
+ };
- protected String toString (T item) {
- return item.toString();
- }
+ list.setTouchable(Touchable.disabled);
+ setActor(list);
- public void showList () {
- if (items.size == 0) return;
- selectBoxList.show(getStage());
- }
+ filterField = new TextField("", selectBox.style.textFieldStyle);
- public void hideList () {
- selectBoxList.hide();
- }
+ list.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ selectBox.selection.choose(list.getSelected());
+ hide();
+ }
- /** Returns the list shown when the select box is open. */
- public List getList () {
- return selectBoxList.list;
- }
+ @Override
+ public boolean mouseMoved(InputEvent event, float x, float y) {
+ list.setSelectedIndex(
+ Math.min(list.getItems().size - 1, (int) ((list.getHeight() - y) / list.getItemHeight())));
+ return true;
+ }
+ });
- /** Disables scrolling of the list shown when the select box is open. */
- public void setScrollingDisabled (boolean y) {
- selectBoxList.setScrollingDisabled(true, y);
- invalidateHierarchy();
- }
+ addListener(new InputListener() {
+ @Override
+ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
+ if (toActor == null || !isAscendantOf(toActor))
+ list.getSelection().set(selectBox.getSelected());
+ }
+ });
- /** Returns the scroll pane containing the list that is shown when the select box is open. */
- public ScrollPane getScrollPane () {
- return selectBoxList;
- }
+ hideListener = new InputListener() {
+ @Override
+ public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
+ Actor target = event.getTarget();
+ if (isAscendantOf(target))
+ return false;
+ list.getSelection().set(selectBox.getSelected());
+ hide();
+ return false;
+ }
- protected void onShow (Actor selectBoxList, boolean below) {
- selectBoxList.getColor().a = 0;
- selectBoxList.addAction(fadeIn(0.3f, Interpolation.fade));
- }
+ @Override
+ public boolean keyDown(InputEvent event, int keycode) {
+ if (keycode == Keys.ESCAPE)
+ hide();
+ return false;
+ }
+ };
- protected void onHide (Actor selectBoxList) {
- selectBoxList.getColor().a = 1;
- selectBoxList.addAction(sequence(fadeOut(0.15f, Interpolation.fade), removeActor()));
- }
+ filterField.addListener(new InputListener() {
+ @Override
+ public boolean keyUp(InputEvent event, int keycode) {
+ if (keycode == Keys.ENTER) {
+ setSelected(list.getSelected());
+ hideList();
+ filterField.setCursorPosition(filterField.getText().length());
+ } else if (keycode == Keys.UP) {
+ int idx = list.getSelectedIndex();
- /** @author Nathan Sweet */
- final class SelectBoxList extends ScrollPane {
- private final FilteredSelectBox selectBox;
- int maxListCount;
- private final Vector2 screenPosition = new Vector2();
- final List list;
- private InputListener hideListener;
- private Actor previousScrollFocus;
- private TextField filterField;
-
- public SelectBoxList (final FilteredSelectBox selectBox) {
- super(null, selectBox.style.scrollStyle);
- this.selectBox = selectBox;
-
- setOverscroll(false, false);
- setFadeScrollBars(false);
- setScrollingDisabled(true, false);
-
- list = new List(selectBox.style.listStyle) {
- @Override
- protected String toString (T obj) {
- return selectBox.toString(obj);
- }
- };
- list.setTouchable(Touchable.disabled);
- setActor(list);
-
- filterField = new TextField("", selectBox.style.textFieldStyle);
-
- list.addListener(new ClickListener() {
- public void clicked (InputEvent event, float x, float y) {
- selectBox.selection.choose(list.getSelected());
- hide();
- }
+ if (idx > 0)
+ list.setSelectedIndex(idx - 1);
- public boolean mouseMoved (InputEvent event, float x, float y) {
- list.setSelectedIndex(Math.min(list.getItems().size - 1, (int)((list.getHeight() - y) / list.getItemHeight())));
return true;
- }
- });
+ } else if (keycode == Keys.DOWN) {
+ int idx = list.getSelectedIndex();
- addListener(new InputListener() {
- public void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {
- if (toActor == null || !isAscendantOf(toActor)) list.getSelection().set(selectBox.getSelected());
- }
- });
+ if (idx < list.getItems().size - 1)
+ list.setSelectedIndex(idx + 1);
- hideListener = new InputListener() {
- public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
- Actor target = event.getTarget();
- if (isAscendantOf(target)) return false;
- list.getSelection().set(selectBox.getSelected());
- hide();
- return false;
- }
-
- public boolean keyDown (InputEvent event, int keycode) {
- if (keycode == Keys.ESCAPE) hide();
- return false;
- }
- };
-
- filterField.addListener(new InputListener() {
- public boolean keyUp(InputEvent event, int keycode) {
- if (keycode == Keys.ENTER) {
- setSelected(list.getSelected());
- hideList();
- filterField.setCursorPosition(filterField.getText().length());
- } else if (keycode == Keys.UP) {
- int idx = list.getSelectedIndex();
-
- if (idx > 0)
- list.setSelectedIndex(idx - 1);
-
- return true;
- } else if (keycode == Keys.DOWN) {
- int idx = list.getSelectedIndex();
-
- if (idx < list.getItems().size - 1)
- list.setSelectedIndex(idx + 1);
-
- return true;
- } else {
- if (getStage() == null && list.getItems().size > 0) {
- showList();
- }
-
- filterItems(filterField.getText());
+ return true;
+ } else {
+ if (getStage() == null && list.getItems().size > 0) {
+ showList();
}
- return false;
+ filterItems(filterField.getText());
}
- });
- }
-
- @SuppressWarnings("unchecked")
- private void filterItems(String s) {
- if (s == null || s.isEmpty()) {
- setListItems((T[])items.toArray());
- } else {
+ return false;
+ }
+ });
+ }
- ArrayList filtered = new ArrayList();
+ @SuppressWarnings("unchecked")
+ private void filterItems(String s) {
- String sl = s.toLowerCase();
+ if (s == null || s.isEmpty()) {
+ setListItems(items.toArray());
+ } else {
- for (T item : (T[])items.toArray()) {
- if (item.toString().toLowerCase().contains(sl))
- filtered.add(item);
- }
+ ArrayList filtered = new ArrayList<>();
- setListItems((T[]) filtered.toArray(new String[filtered.size()]));
+ String sl = s.toLowerCase();
+
+ for (T item : items.toArray()) {
+ if (item.toString().toLowerCase().contains(sl))
+ filtered.add(item);
}
-// hideList();
- invalidate();
-// showList();
+ setListItems((T[]) filtered.toArray(new String[filtered.size()]));
}
-
- private final void setListItems(T[] newItems) {
- if (newItems == null)
- throw new IllegalArgumentException("newItems cannot be null.");
- float oldPrefWidth = getPrefWidth();
-
- list.setItems(newItems);
- if (newItems.length > 0)
- list.setSelectedIndex(0);
- else
- list.setSelectedIndex(-1);
+// hideList();
+ invalidate();
+// showList();
+ }
- invalidate();
- if (oldPrefWidth != getPrefWidth())
- invalidateHierarchy();
- }
+ private final void setListItems(T[] newItems) {
+ if (newItems == null)
+ throw new IllegalArgumentException("newItems cannot be null.");
- public void show (Stage stage) {
- if (list.isTouchable()) return;
+ float oldPrefWidth = getPrefWidth();
- stage.removeCaptureListener(hideListener);
- stage.addCaptureListener(hideListener);
- stage.addActor(this);
- stage.addActor(filterField);
-
- selectBox.localToStageCoordinates(screenPosition.set(0, 0));
-
- // Show the list above or below the select box, limited to a number of items and the available height in the stage.
- float itemHeight = list.getItemHeight();
- float height = itemHeight * (maxListCount <= 0 ? selectBox.items.size : Math.min(maxListCount, selectBox.items.size));
- Drawable scrollPaneBackground = getStyle().background;
- if (scrollPaneBackground != null) height += scrollPaneBackground.getTopHeight() + scrollPaneBackground.getBottomHeight();
- Drawable listBackground = list.getStyle().background;
- if (listBackground != null) height += listBackground.getTopHeight() + listBackground.getBottomHeight();
-
- float heightBelow = screenPosition.y - itemHeight;
- float heightAbove = stage.getCamera().viewportHeight - screenPosition.y - selectBox.getHeight();
- boolean below = true;
- if (height > heightBelow) {
- if (heightAbove > heightBelow) {
- below = false;
- height = Math.min(height, heightAbove);
- } else
- height = heightBelow;
- }
+ list.setItems(newItems);
+ if (newItems.length > 0)
+ list.setSelectedIndex(0);
+ else
+ list.setSelectedIndex(-1);
- if (below)
- setY(screenPosition.y - height);
- else
- setY(screenPosition.y + selectBox.getHeight());
- setX(screenPosition.x);
- setHeight(height);
- validate();
- float width = Math.max(getPrefWidth(), selectBox.getWidth());
- if (getPrefHeight() > height && !isScrollingDisabledY()) width += getScrollBarWidth();
- setWidth(width);
-
- filterField.setX(getX());
- filterField.setWidth(getWidth());
- filterField.setHeight(filterField.getPrefHeight());
- filterField.setY(getY() + getHeight() - filterField.getHeight());
- stage.setKeyboardFocus(filterField);
- filterField.validate();
- setY(getY() - filterField.getHeight());
-
- validate();
- scrollTo(0, list.getHeight() - selectBox.getSelectedIndex() * itemHeight - itemHeight / 2, 0, 0, true, true);
- updateVisualScroll();
-
- previousScrollFocus = null;
- Actor actor = stage.getScrollFocus();
- if (actor != null && !actor.isDescendantOf(this)) previousScrollFocus = actor;
- stage.setScrollFocus(this);
-
- list.getSelection().set(selectBox.getSelected());
- list.setTouchable(Touchable.enabled);
- clearActions();
- selectBox.onShow(this, below);
-
- filterField.setText("");
- setListItems((T[])items.toArray());
+ invalidate();
+ if (oldPrefWidth != getPrefWidth())
+ invalidateHierarchy();
+ }
+
+ public void show(Stage stage) {
+ if (list.isTouchable())
+ return;
+
+ stage.removeCaptureListener(hideListener);
+ stage.addCaptureListener(hideListener);
+ stage.addActor(this);
+ stage.addActor(filterField);
+
+ selectBox.localToStageCoordinates(screenPosition.set(0, 0));
+
+ // Show the list above or below the select box, limited to a number of items and
+ // the available height in the stage.
+ float itemHeight = list.getItemHeight();
+ float height = itemHeight
+ * (maxListCount <= 0 ? selectBox.items.size : Math.min(maxListCount, selectBox.items.size));
+ Drawable scrollPaneBackground = getStyle().background;
+ if (scrollPaneBackground != null)
+ height += scrollPaneBackground.getTopHeight() + scrollPaneBackground.getBottomHeight();
+ Drawable listBackground = list.getStyle().background;
+ if (listBackground != null)
+ height += listBackground.getTopHeight() + listBackground.getBottomHeight();
+
+ float heightBelow = screenPosition.y - itemHeight;
+ float heightAbove = stage.getCamera().viewportHeight - screenPosition.y - selectBox.getHeight();
+ boolean below = true;
+ if (height > heightBelow) {
+ if (heightAbove > heightBelow) {
+ below = false;
+ height = Math.min(height, heightAbove);
+ } else
+ height = heightBelow;
}
- public void hide () {
- if (!list.isTouchable() || !hasParent()) return;
- list.setTouchable(Touchable.disabled);
+ if (below)
+ setY(screenPosition.y - height);
+ else
+ setY(screenPosition.y + selectBox.getHeight());
+ setX(screenPosition.x);
+ setHeight(height);
+ validate();
+ float width = Math.max(getPrefWidth(), selectBox.getWidth());
+ if (getPrefHeight() > height && !isScrollingDisabledY())
+ width += getScrollBarWidth();
+ setWidth(width);
+
+ filterField.setX(getX());
+ filterField.setWidth(getWidth());
+ filterField.setHeight(filterField.getPrefHeight());
+ filterField.setY(getY() + getHeight() - filterField.getHeight());
+ stage.setKeyboardFocus(filterField);
+ filterField.validate();
+ setY(getY() - filterField.getHeight());
- Stage stage = getStage();
- if (stage != null) {
- stage.removeCaptureListener(hideListener);
- if (previousScrollFocus != null && previousScrollFocus.getStage() == null) previousScrollFocus = null;
- Actor actor = stage.getScrollFocus();
- if (actor == null || isAscendantOf(actor)) stage.setScrollFocus(previousScrollFocus);
- }
+ validate();
+ scrollTo(0, list.getHeight() - selectBox.getSelectedIndex() * itemHeight - itemHeight / 2, 0, 0, true,
+ true);
+ updateVisualScroll();
- clearActions();
- selectBox.onHide(this);
- filterField.remove();
- }
+ previousScrollFocus = null;
+ Actor actor = stage.getScrollFocus();
+ if (actor != null && !actor.isDescendantOf(this))
+ previousScrollFocus = actor;
+ stage.setScrollFocus(this);
- public void draw (Batch batch, float parentAlpha) {
- selectBox.localToStageCoordinates(temp.set(0, 0));
- if (!temp.equals(screenPosition)) hide();
- super.draw(batch, parentAlpha);
- }
+ list.getSelection().set(selectBox.getSelected());
+ list.setTouchable(Touchable.enabled);
+ clearActions();
+ selectBox.onShow(this, below);
- public void act (float delta) {
- super.act(delta);
- toFront();
- filterField.toFront();
- }
+ filterField.setText("");
+ setListItems(items.toArray());
}
- /** The style for a select box, see {@link SelectBox}.
- * @author mzechner
- * @author Nathan Sweet */
- static public class FilteredSelectBoxStyle {
- public BitmapFont font;
- public Color fontColor = new Color(1, 1, 1, 1);
- /** Optional. */
- public Color disabledFontColor;
- /** Optional. */
- public Drawable background;
- public ScrollPaneStyle scrollStyle;
- public ListStyle listStyle;
- public TextFieldStyle textFieldStyle;
- /** Optional. */
- public Drawable backgroundOver, backgroundOpen, backgroundDisabled;
-
- public FilteredSelectBoxStyle () {
- }
+ public void hide() {
+ if (!list.isTouchable() || !hasParent())
+ return;
+ list.setTouchable(Touchable.disabled);
- public FilteredSelectBoxStyle (BitmapFont font, Color fontColor, Drawable background, ScrollPaneStyle scrollStyle,
- ListStyle listStyle, TextFieldStyle textFieldStyle) {
- this.font = font;
- this.fontColor.set(fontColor);
- this.background = background;
- this.scrollStyle = scrollStyle;
- this.listStyle = listStyle;
- this.textFieldStyle = textFieldStyle;
+ Stage stage = getStage();
+ if (stage != null) {
+ stage.removeCaptureListener(hideListener);
+ if (previousScrollFocus != null && previousScrollFocus.getStage() == null)
+ previousScrollFocus = null;
+ Actor actor = stage.getScrollFocus();
+ if (actor == null || isAscendantOf(actor))
+ stage.setScrollFocus(previousScrollFocus);
}
- public FilteredSelectBoxStyle (FilteredSelectBoxStyle style) {
- this.font = style.font;
- this.fontColor.set(style.fontColor);
- if (style.disabledFontColor != null) this.disabledFontColor = new Color(style.disabledFontColor);
- this.background = style.background;
- this.backgroundOver = style.backgroundOver;
- this.backgroundOpen = style.backgroundOpen;
- this.backgroundDisabled = style.backgroundDisabled;
- this.scrollStyle = new ScrollPaneStyle(style.scrollStyle);
- this.listStyle = new ListStyle(style.listStyle);
- this.textFieldStyle = new TextFieldStyle(style.textFieldStyle);
- }
+ clearActions();
+ selectBox.onHide(this);
+ filterField.remove();
}
+ @Override
+ public void draw(Batch batch, float parentAlpha) {
+ selectBox.localToStageCoordinates(temp.set(0, 0));
+ if (!temp.equals(screenPosition))
+ hide();
+ super.draw(batch, parentAlpha);
+ }
+
+ @Override
+ public void act(float delta) {
+ super.act(delta);
+ toFront();
+ filterField.toFront();
+ }
+ }
+
+ /**
+ * The style for a select box, see {@link SelectBox}.
+ *
+ * @author mzechner
+ * @author Nathan Sweet
+ */
+ static public class FilteredSelectBoxStyle {
+ public BitmapFont font;
+ public Color fontColor = new Color(1, 1, 1, 1);
+ /** Optional. */
+ public Color disabledFontColor;
+ /** Optional. */
+ public Drawable background;
+ public ScrollPaneStyle scrollStyle;
+ public ListStyle listStyle;
+ public TextFieldStyle textFieldStyle;
+ /** Optional. */
+ public Drawable backgroundOver, backgroundOpen, backgroundDisabled;
+
+ public FilteredSelectBoxStyle() {
+ }
+
+ public FilteredSelectBoxStyle(BitmapFont font, Color fontColor, Drawable background,
+ ScrollPaneStyle scrollStyle, ListStyle listStyle, TextFieldStyle textFieldStyle) {
+ this.font = font;
+ this.fontColor.set(fontColor);
+ this.background = background;
+ this.scrollStyle = scrollStyle;
+ this.listStyle = listStyle;
+ this.textFieldStyle = textFieldStyle;
+ }
+
+ public FilteredSelectBoxStyle(FilteredSelectBoxStyle style) {
+ this.font = style.font;
+ this.fontColor.set(style.fontColor);
+ if (style.disabledFontColor != null)
+ this.disabledFontColor = new Color(style.disabledFontColor);
+ this.background = style.background;
+ this.backgroundOver = style.backgroundOver;
+ this.backgroundOpen = style.backgroundOpen;
+ this.backgroundDisabled = style.backgroundDisabled;
+ this.scrollStyle = new ScrollPaneStyle(style.scrollStyle);
+ this.listStyle = new ListStyle(style.listStyle);
+ this.textFieldStyle = new TextFieldStyle(style.textFieldStyle);
+ }
+ }
+
}
diff --git a/adventure-editor/src/main/java/com/bladecoder/engineeditor/ui/panels/ModelList.java b/adventure-editor/src/main/java/com/bladecoder/engineeditor/ui/panels/ModelList.java
index d6de12848..6830c434d 100644
--- a/adventure-editor/src/main/java/com/bladecoder/engineeditor/ui/panels/ModelList.java
+++ b/adventure-editor/src/main/java/com/bladecoder/engineeditor/ui/panels/ModelList.java
@@ -61,7 +61,7 @@ public void addElements(PARENT parent, List elements) {
if (sorted) {
list.sortByTitle();
}
-
+
if (getItems().size > 0)
list.getSelection().choose(list.getItems().get(0));
@@ -81,8 +81,11 @@ protected void create() {
@Override
public void changed(ChangeEvent event, Actor actor) {
T e = ((EditModelDialog) actor).getElement();
- addItem(e);
-
+
+ if (getItems().indexOf(e, true) == -1) {
+ addItem(e);
+ }
+
if (sorted) {
list.sortByTitle();
}
diff --git a/adventure-editor/src/main/java/com/bladecoder/engineeditor/undo/UndoDeleteVerb.java b/adventure-editor/src/main/java/com/bladecoder/engineeditor/undo/UndoDeleteVerb.java
index e184c4c48..253eac9da 100644
--- a/adventure-editor/src/main/java/com/bladecoder/engineeditor/undo/UndoDeleteVerb.java
+++ b/adventure-editor/src/main/java/com/bladecoder/engineeditor/undo/UndoDeleteVerb.java
@@ -5,15 +5,15 @@
import com.bladecoder.engineeditor.Ctx;
import com.bladecoder.engineeditor.model.Project;
-
public class UndoDeleteVerb implements UndoOp {
private VerbManager vm;
private Verb v;
-
+
public UndoDeleteVerb(VerbManager vm, Verb v) {
this.vm = vm;
+ this.v = v;
}
-
+
@Override
public void undo() {
vm.addVerb(v);
diff --git a/adventure-editor/src/main/resources/images/icons.atlas b/adventure-editor/src/main/resources/images/icons.atlas
index 17818dd80..deeb27f7f 100644
--- a/adventure-editor/src/main/resources/images/icons.atlas
+++ b/adventure-editor/src/main/resources/images/icons.atlas
@@ -153,7 +153,7 @@ ic_create_all
index: -1
ic_create_all_disabled
rotate: false
- xy: 861, 51
+ xy: 913, 51
size: 15, 15
orig: 15, 15
offset: 0, 0
@@ -424,6 +424,20 @@ ic_quit
orig: 45, 45
offset: 0, 0
index: -1
+ic_reload_small
+ rotate: false
+ xy: 651, 42
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: -1
+ic_reload_small_disabled
+ rotate: false
+ xy: 677, 42
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: -1
ic_repeat
rotate: false
xy: 326, 47
@@ -433,14 +447,14 @@ ic_repeat
index: -1
ic_right
rotate: false
- xy: 651, 42
+ xy: 703, 42
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
ic_right_disabled
rotate: false
- xy: 677, 42
+ xy: 729, 42
size: 24, 24
orig: 24, 24
offset: 0, 0
@@ -489,14 +503,14 @@ ic_text
index: -1
ic_up
rotate: false
- xy: 703, 42
+ xy: 755, 42
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
ic_up_disabled
rotate: false
- xy: 729, 42
+ xy: 781, 42
size: 24, 24
orig: 24, 24
offset: 0, 0
@@ -538,21 +552,21 @@ scn_move
index: -1
scn_rotate
rotate: false
- xy: 755, 42
+ xy: 807, 42
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
scn_scale
rotate: false
- xy: 805, 48
+ xy: 857, 48
size: 18, 18
orig: 18, 18
offset: 0, 0
index: -1
scn_scale_lock
rotate: false
- xy: 781, 44
+ xy: 833, 44
size: 22, 22
orig: 22, 22
offset: 0, 0
@@ -573,14 +587,14 @@ title
index: -1
transparent-dark
rotate: false
- xy: 825, 50
+ xy: 877, 50
size: 16, 16
orig: 16, 16
offset: 0, 0
index: -1
transparent-light
rotate: false
- xy: 843, 50
+ xy: 895, 50
size: 16, 16
orig: 16, 16
offset: 0, 0
diff --git a/adventure-editor/src/main/resources/images/icons.png b/adventure-editor/src/main/resources/images/icons.png
index 4705d447e..6aa6ac77d 100644
Binary files a/adventure-editor/src/main/resources/images/icons.png and b/adventure-editor/src/main/resources/images/icons.png differ
diff --git a/adventure-editor/src/main/resources/projectTmpl/android/AndroidManifest.xml b/adventure-editor/src/main/resources/projectTmpl/android/AndroidManifest.xml
index 51bc1f818..35d8642fe 100644
--- a/adventure-editor/src/main/resources/projectTmpl/android/AndroidManifest.xml
+++ b/adventure-editor/src/main/resources/projectTmpl/android/AndroidManifest.xml
@@ -1,10 +1,12 @@
+
+
diff --git a/adventure-editor/src/main/resources/projectTmpl/android/build.gradle b/adventure-editor/src/main/resources/projectTmpl/android/build.gradle
index e74a5fea7..7332a9b6d 100644
--- a/adventure-editor/src/main/resources/projectTmpl/android/build.gradle
+++ b/adventure-editor/src/main/resources/projectTmpl/android/build.gradle
@@ -5,7 +5,7 @@ android {
defaultConfig {
applicationId "%PACKAGE%"
- minSdkVersion 15
+ minSdkVersion 21
targetSdkVersion '%API_LEVEL%'
versionName version
@@ -86,7 +86,7 @@ android {
configurations { natives }
dependencies {
- api project(":core")
+ implementation project(":core")
api "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
@@ -101,6 +101,8 @@ dependencies {
// TO QUERY PERMISSIONS
implementation "com.android.support:support-v4:23.0.0"
+
+ implementation "com.badlogicgames.gdx-controllers:gdx-controllers-android:$gdxControllersVersion"
}
// called every time gradle gets executed, takes the native dependencies of
@@ -130,6 +132,12 @@ task copyAndroidNatives() {
}
}
+tasks.whenTaskAdded { packageTask ->
+ if (packageTask.name.contains("package")) {
+ packageTask.dependsOn 'copyAndroidNatives'
+ }
+}
+
task run(type: Exec) {
def path
def localProperties = project.file("../local.properties")
@@ -149,7 +157,7 @@ task run(type: Exec) {
}
def adb = path + "/platform-tools/adb"
- commandLine "$adb", 'shell', 'am', 'start', '-n', android.defaultConfig.applicationId + '/' + android.defaultConfig.applicationId + '.AndroidLauncher'
+ commandLine "$adb", 'shell', 'am', 'start', '-n', android.defaultConfig.applicationId + '/' + 'com.bladecoder.engine.AndroidLauncher'
}
task('packageMainExpansionFile', type: Zip) {
@@ -175,61 +183,6 @@ tasks.whenTaskAdded { task ->
}
}
-// sets up the Android Eclipse project, using the old Ant based build.
-eclipse {
- // need to specify Java source sets explicitely, SpringSource Gradle Eclipse plugin
- // ignores any nodes added in classpath.file.withXml
- sourceSets {
- main {
- java.srcDirs "src/main/java", 'gen'
- }
- }
-
- jdt {
- sourceCompatibility=1.7
- targetCompatibility=1.7
- }
-
- classpath {
- plusConfigurations += [ project.configurations.compile ]
- containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'
- }
-
- project {
- name = appName + "-android"
- natures 'com.android.ide.eclipse.adt.AndroidNature'
- buildCommands.clear();
- buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
- buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
- buildCommand "org.eclipse.jdt.core.javabuilder"
- buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
- }
-}
-
-// sets up the Android Idea project, using the old Ant based build.
-idea {
- module {
- sourceDirs += file("src");
- scopes = [ COMPILE: [plus:[project.configurations.compile]]]
-
- iml {
- withXml {
- def node = it.asNode()
- def builder = NodeBuilder.newInstance();
- builder.current = node;
- builder.component(name: "FacetManager") {
- facet(type: "android", name: "Android") {
- configuration {
- option(name: "UPDATE_PROPERTY_FILES", value:"true")
- }
- }
- }
- }
- }
- }
-}
-
-
String highestSdkAvailable(String defaultSdk) {
try {
def buildToolsDir = new File(android.getSdkDirectory().toString(), "platforms")
diff --git a/adventure-editor/src/main/resources/projectTmpl/android/src/AndroidLauncher b/adventure-editor/src/main/resources/projectTmpl/android/src/AndroidLauncher
index a954355d6..a34d4b4d9 100644
--- a/adventure-editor/src/main/resources/projectTmpl/android/src/AndroidLauncher
+++ b/adventure-editor/src/main/resources/projectTmpl/android/src/AndroidLauncher
@@ -1,4 +1,4 @@
-package %PACKAGE%;
+package com.bladecoder.engine;
import com.bladecoder.engine.BladeEngine;
@@ -54,21 +54,20 @@ public class AndroidLauncher extends AndroidApplication {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
- Log.v(TAG, "Permission is granted but .obb was not found.");
+ Log.e(TAG, "Permission is granted but .obb was not found.");
// TODO Download .obb
exit();
} else {
Log.v(TAG, "Permission is revoked, requesting...");
+ bladeEngine.setWaitingForPermissions(true);
ActivityCompat.requestPermissions(AndroidLauncher.this,
new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, 2);
}
} else { // permission is automatically granted on sdk<23 upon installation
- Log.v(TAG, "Permission is granted in Manifest (sdk<23) but .obb was not found.");
+ Log.e(TAG, "Permission is granted in Manifest (sdk<23) but .obb was not found.");
// TODO Download .obb
exit();
}
- } else {
- bladeEngine.createWithExpansion();
}
}
}
@@ -85,15 +84,13 @@ public class AndroidLauncher extends AndroidApplication {
boolean success = ((AndroidFiles) Gdx.files).setAPKExpansion(BuildConfig.EXPANSION_FILE_VERSION, 0);
if (!success) {
- Log.v(TAG, "Permission accepted but .obb was not found.");
+ Log.e(TAG, "Permission accepted but .obb was not found.");
// TODO Download .obb
exit();
- } else {
- bladeEngine.createWithExpansion();
- }
+ }
} else {
- Log.v(TAG, "Permission denied by user.");
+ Log.e(TAG, "Permission denied by user.");
exit();
}
break;
@@ -112,17 +109,40 @@ public class AndroidLauncher extends AndroidApplication {
}
class AndroidEngine extends BladeEngine {
+ private boolean waitingForPermissions = false;
+
@Override
public void create() {
- if (BuildConfig.EXPANSION_FILE_VERSION == 0) {
- super.create();
+ if(waitingForPermissions)
+ return;
+
+ if (BuildConfig.EXPANSION_FILE_VERSION > 0) {
+ boolean success = ((AndroidFiles) Gdx.files).setAPKExpansion(BuildConfig.EXPANSION_FILE_VERSION, 0);
+
+ if(!success) {
+ Log.e(TAG, "Can not set APK expansion.");
+ Gdx.app.exit();
+ } else {
+ Log.d(TAG, "Expansion file stablish successfully!");
+ }
}
+
+ super.create();
}
- public void createWithExpansion() {
- ((AndroidFiles) Gdx.files).setAPKExpansion(BuildConfig.EXPANSION_FILE_VERSION, 0);
+ @Override
+ public void resume() {
+ if(waitingForPermissions) {
+ // returns from querying permissions
+ bladeEngine.setWaitingForPermissions(false);
+ bladeEngine.create();
+ }
+
+ super.resume();
+ }
- super.create();
+ public void setWaitingForPermissions(boolean v) {
+ waitingForPermissions = v;
}
}
}
\ No newline at end of file
diff --git a/adventure-editor/src/main/resources/projectTmpl/assets/BladeEngine.properties b/adventure-editor/src/main/resources/projectTmpl/assets/BladeEngine.properties
index 4aedc72d4..f7f3c56d4 100644
--- a/adventure-editor/src/main/resources/projectTmpl/assets/BladeEngine.properties
+++ b/adventure-editor/src/main/resources/projectTmpl/assets/BladeEngine.properties
@@ -2,7 +2,6 @@ title=Blade Engine Adventure
ui_mode=two_buttons
inventory_pos=down
debug=false
-#load_gamestate=
-#play_recording=full
-#force_res=1920
+resolutions=1
+
diff --git a/adventure-editor/src/main/resources/projectTmpl/core/build.gradle b/adventure-editor/src/main/resources/projectTmpl/core/build.gradle
index aac4e67c4..a804b2a23 100644
--- a/adventure-editor/src/main/resources/projectTmpl/core/build.gradle
+++ b/adventure-editor/src/main/resources/projectTmpl/core/build.gradle
@@ -5,7 +5,6 @@ sourceCompatibility = 1.7
targetCompatibility=1.7
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
-eclipse.project.name = appName + '-core'
dependencies {
api "com.badlogicgames.gdx:gdx:$gdxVersion"
@@ -14,6 +13,8 @@ dependencies {
implementation "com.bladecoder.ink:blade-ink:$bladeInkVersion"
implementation "org.minimalcode:minimalcode-beans:0.5.1"
implementation "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
+ implementation "com.badlogicgames.gdx-controllers:gdx-controllers-core:$gdxControllersVersion"
+
if(project.hasProperty("spinePlugin") && project.spinePlugin.equals("true")) {
println "Using Spine Plugin..."
diff --git a/adventure-editor/src/main/resources/projectTmpl/desktop/build.gradle b/adventure-editor/src/main/resources/projectTmpl/desktop/build.gradle
index 355ddeb35..98ee7855f 100644
--- a/adventure-editor/src/main/resources/projectTmpl/desktop/build.gradle
+++ b/adventure-editor/src/main/resources/projectTmpl/desktop/build.gradle
@@ -6,14 +6,14 @@ targetCompatibility=1.7
sourceSets.main.resources.srcDirs += [ rootProject.file('assets').absolutePath ]
-mainClassName = "%PACKAGE%.desktop.DesktopLauncher"
-eclipse.project.name = appName + '-desktop'
+mainClassName = "com.bladecoder.engine.DesktopLauncher"
dependencies {
implementation project(":core")
implementation "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion"
implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
implementation "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
+ implementation "com.badlogicgames.gdx-controllers:gdx-controllers-desktop:$gdxControllersVersion"
}
run {
diff --git a/adventure-editor/src/main/resources/projectTmpl/desktop/src/DesktopLauncher b/adventure-editor/src/main/resources/projectTmpl/desktop/src/DesktopLauncher
index df8cf30d1..6abe6df01 100644
--- a/adventure-editor/src/main/resources/projectTmpl/desktop/src/DesktopLauncher
+++ b/adventure-editor/src/main/resources/projectTmpl/desktop/src/DesktopLauncher
@@ -1,4 +1,4 @@
-package %PACKAGE%.desktop;
+package com.bladecoder.engine;
import java.io.IOException;
import java.io.InputStream;
diff --git a/adventure-editor/src/main/resources/projectTmpl/gradle.properties b/adventure-editor/src/main/resources/projectTmpl/gradle.properties
index 5294df70a..8b99e8296 100644
--- a/adventure-editor/src/main/resources/projectTmpl/gradle.properties
+++ b/adventure-editor/src/main/resources/projectTmpl/gradle.properties
@@ -9,6 +9,7 @@ androidGradlePluginVersion=%ANDROID_GRADLE_PLUGIN_VERSION%
bladeInkVersion=%BLADE_INK_VERSION%
spinePlugin=%USE_SPINE%
+gdxControllersVersion=2.0.1
org.gradle.daemon=true
org.gradle.jvmargs=-Xms128m -Xmx1536m
diff --git a/adventure-editor/src/main/resources/projectTmpl/gradle/wrapper/gradle-wrapper.properties b/adventure-editor/src/main/resources/projectTmpl/gradle/wrapper/gradle-wrapper.properties
index e0b3fb8d7..4d9ca1649 100644
--- a/adventure-editor/src/main/resources/projectTmpl/gradle/wrapper/gradle-wrapper.properties
+++ b/adventure-editor/src/main/resources/projectTmpl/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/adventure-editor/src/main/resources/projectTmpl/ios/Info.plist.xml b/adventure-editor/src/main/resources/projectTmpl/ios/Info.plist.xml
index 7b4e11581..773249514 100644
--- a/adventure-editor/src/main/resources/projectTmpl/ios/Info.plist.xml
+++ b/adventure-editor/src/main/resources/projectTmpl/ios/Info.plist.xml
@@ -5,7 +5,7 @@
UIRequiresFullScreen
yes
MinimumOSVersion
- 7.0
+ 8.0
CFBundleDevelopmentRegion
en
@@ -40,7 +40,6 @@
UIRequiredDeviceCapabilities
- armv7
opengles-2
UISupportedInterfaceOrientations
@@ -50,5 +49,15 @@
CFBundleIconName
AppIcon
+
+ GCSupportedGameControllers
+
+
+ ProfileName
+ ExtendedGamepad
+
+
+ GCSupportsControllerUserInteraction
+
diff --git a/adventure-editor/src/main/resources/projectTmpl/ios/build.gradle b/adventure-editor/src/main/resources/projectTmpl/ios/build.gradle
index cb4421b7c..86fa8f6c7 100644
--- a/adventure-editor/src/main/resources/projectTmpl/ios/build.gradle
+++ b/adventure-editor/src/main/resources/projectTmpl/ios/build.gradle
@@ -6,7 +6,7 @@ sourceCompatibility = 1.7
targetCompatibility=1.7
ext {
- mainClassName = "%PACKAGE%.IOSLauncher"
+ mainClassName = "com.bladecoder.engine.IOSLauncher"
}
launchIPhoneSimulator.dependsOn build
@@ -30,4 +30,6 @@ dependencies {
compile "com.badlogicgames.gdx:gdx-backend-robovm:$gdxVersion"
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios"
compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-ios"
+
+ implementation "com.badlogicgames.gdx-controllers:gdx-controllers-ios:$gdxControllersVersion"
}
diff --git a/adventure-editor/src/main/resources/projectTmpl/ios/robovm.properties b/adventure-editor/src/main/resources/projectTmpl/ios/robovm.properties
index f0ccc54cd..05619e28e 100644
--- a/adventure-editor/src/main/resources/projectTmpl/ios/robovm.properties
+++ b/adventure-editor/src/main/resources/projectTmpl/ios/robovm.properties
@@ -1,6 +1,6 @@
app.version=1.0
app.id=%PACKAGE%
-app.mainclass=%PACKAGE%.IOSLauncher
+app.mainclass=com.bladecoder.engine.IOSLauncher
app.executable=IOSLauncher
app.build=1
app.name=%APP_NAME%
diff --git a/adventure-editor/src/main/resources/projectTmpl/ios/robovm.xml b/adventure-editor/src/main/resources/projectTmpl/ios/robovm.xml
index d729ad43c..2d5086b41 100644
--- a/adventure-editor/src/main/resources/projectTmpl/ios/robovm.xml
+++ b/adventure-editor/src/main/resources/projectTmpl/ios/robovm.xml
@@ -34,6 +34,7 @@
com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryOpenSSL
org.apache.harmony.security.provider.cert.DRLCertFactory
org.apache.harmony.security.provider.crypto.CryptoProvider
+ com.badlogic.gdx.controllers.IosControllerManager
z
@@ -46,6 +47,7 @@
OpenAL
AudioToolbox
AVFoundation
+ GameKit
diff --git a/adventure-editor/src/main/resources/projectTmpl/ios/src/IOSLauncher b/adventure-editor/src/main/resources/projectTmpl/ios/src/IOSLauncher
index 18e7dc684..11b966e44 100644
--- a/adventure-editor/src/main/resources/projectTmpl/ios/src/IOSLauncher
+++ b/adventure-editor/src/main/resources/projectTmpl/ios/src/IOSLauncher
@@ -1,4 +1,4 @@
-package %PACKAGE%;
+package com.bladecoder.engine;
import org.robovm.apple.foundation.NSAutoreleasePool;
import org.robovm.apple.uikit.UIApplication;
diff --git a/adventure-editor/src/main/resources/versions.properties b/adventure-editor/src/main/resources/versions.properties
index da89e7592..a9474d91c 100644
--- a/adventure-editor/src/main/resources/versions.properties
+++ b/adventure-editor/src/main/resources/versions.properties
@@ -1,8 +1,7 @@
-androidAPILevel=27
-androidGradlePluginVersion=3.2.1
-bladeInkVersion=0.5.1
-buildToolsVersion=28.0.3
-libgdxVersion=1.9.9
-roboVMGradlePluginVersion=2.3.5
-roboVMVersion=2.3.5
-version=3.1.1-SNAPSHOT
+androidAPILevel=30
+androidGradlePluginVersion=3.5.4
+bladeInkVersion=0.7.4
+libgdxVersion=1.9.13
+roboVMGradlePluginVersion=2.3.12
+roboVMVersion=2.3.12
+version=4.0.2
diff --git a/blade-engine-spine-plugin/build.gradle b/blade-engine-spine-plugin/build.gradle
index 415323fa1..455cac023 100644
--- a/blade-engine-spine-plugin/build.gradle
+++ b/blade-engine-spine-plugin/build.gradle
@@ -1,7 +1,7 @@
apply plugin: "java"
apply plugin: 'java-library'
-apply plugin: "maven"
apply plugin: "signing"
+apply plugin: "maven"
group = 'com.bladecoder.engine'
@@ -34,7 +34,7 @@ jar {
dependencies {
api "com.badlogicgames.gdx:gdx:$libgdxVersion"
- api "com.esotericsoftware.spine:spine-libgdx:3.7.83.1"
+ api "com.esotericsoftware.spine:spine-libgdx:3.8.55.1"
implementation project(":blade-engine")
}
@@ -52,7 +52,7 @@ task sourcesJar(type: Jar) {
}
artifacts {
- archives jar
+ //archives jar
archives enginedocJar
archives sourcesJar
}
diff --git a/blade-engine-spine-plugin/src/main/java/com/bladecoder/engine/spine/SpineRenderer.java b/blade-engine-spine-plugin/src/main/java/com/bladecoder/engine/spine/SpineRenderer.java
index 08ac75376..579abc2e1 100644
--- a/blade-engine-spine-plugin/src/main/java/com/bladecoder/engine/spine/SpineRenderer.java
+++ b/blade-engine-spine-plugin/src/main/java/com/bladecoder/engine/spine/SpineRenderer.java
@@ -309,18 +309,18 @@ public void setSkin(String skin) {
// Get the source skins.
Skin singleSkin = skeletonData.findSkin(sk.trim());
- combinedSkin.addAttachments(singleSkin);
-
- // Set and apply the Skin to the skeleton.
- sce.skeleton.setSkin(combinedSkin);
+ combinedSkin.addSkin(singleSkin);
}
+
+ // Set and apply the Skin to the skeleton.
+ sce.skeleton.setSkin(combinedSkin);
}
} else {
sce.skeleton.setSkin((Skin) null);
}
- sce.skeleton.setSlotsToSetupPose();
+ // sce.skeleton.setSlotsToSetupPose();
}
this.skin = skin;
@@ -446,9 +446,24 @@ public void setSecondaryAnimation(String animation) {
}
}
+ public Skeleton getCurrentSkeleton() {
+ SkeletonCacheEntry cs = (SkeletonCacheEntry) currentSource;
+ return cs.skeleton;
+ }
+
+ public AnimationState getCurrentAnimationState() {
+ SkeletonCacheEntry cs = (SkeletonCacheEntry) currentSource;
+ return cs.animation;
+ }
+
private void setCurrentAnimation() {
try {
SkeletonCacheEntry cs = (SkeletonCacheEntry) currentSource;
+
+ if (skin != null && (cs.skeleton.getSkin() == null || !skin.equals(cs.skeleton.getSkin().getName()))) {
+ setSkin(skin);
+ }
+
cs.skeleton.setToSetupPose();
cs.skeleton.setScaleX(flipX ? -1 : 1);
cs.animation.setTimeScale(currentAnimation.duration);
@@ -660,9 +675,6 @@ public void retrieveAssets() {
} else if (initAnimation != null) {
startAnimation(initAnimation, Tween.Type.SPRITE_DEFINED, 1, null);
}
-
- setSkin(skin);
- computeBbox();
}
@Override
@@ -692,8 +704,9 @@ public void write(Json json) {
} else {
- if (animationCb != null)
- json.writeValue("cb", ActionCallbackSerializer.find(bjson.getWorld(), animationCb));
+ if (animationCb != null) {
+ json.writeValue("cb", ActionCallbackSerializer.find(bjson.getWorld(), bjson.getScene(), animationCb));
+ }
json.writeValue("currentCount", currentCount);
@@ -721,7 +734,7 @@ public void read(Json json, JsonValue jsonData) {
world = bjson.getWorld();
} else {
- animationCb = ActionCallbackSerializer.find(((BladeJson) json).getWorld(),
+ animationCb = ActionCallbackSerializer.find(((BladeJson) json).getWorld(), ((BladeJson) json).getScene(),
json.readValue("cb", String.class, jsonData));
currentCount = json.readValue("currentCount", Integer.class, jsonData);
diff --git a/blade-engine/build.gradle b/blade-engine/build.gradle
index d720a9411..593a76131 100644
--- a/blade-engine/build.gradle
+++ b/blade-engine/build.gradle
@@ -1,7 +1,7 @@
apply plugin: 'java-library'
apply plugin: "java"
-apply plugin: "maven"
apply plugin: "signing"
+apply plugin: "maven"
group = 'com.bladecoder.engine'
@@ -43,6 +43,7 @@ javadoc {
dependencies {
api "com.badlogicgames.gdx:gdx:$libgdxVersion"
+ implementation "com.badlogicgames.gdx-controllers:gdx-controllers-core:$gdxControllersVersion"
implementation "com.badlogicgames.gdx:gdx-freetype:$libgdxVersion"
implementation "com.bladecoder.ink:blade-ink:$bladeInkVersion"
api fileTree(dir: 'libs', include: '*.jar')
@@ -61,7 +62,7 @@ task sourcesJar(type: Jar) {
}
artifacts {
- archives jar
+ //archives jar
archives enginedocJar
archives sourcesJar
}
diff --git a/blade-engine/src/com/bladecoder/engine/BladeEngine.java b/blade-engine/src/com/bladecoder/engine/BladeEngine.java
index d20757564..395ec73ff 100644
--- a/blade-engine/src/com/bladecoder/engine/BladeEngine.java
+++ b/blade-engine/src/com/bladecoder/engine/BladeEngine.java
@@ -19,6 +19,7 @@
import java.nio.IntBuffer;
import java.text.MessageFormat;
+import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
@@ -77,20 +78,18 @@ public void forceResolution(String forceRes) {
public UI getUI() {
return ui;
}
-
+
public void loadGame(String baseFolder) {
- if(ui != null) {
+ if (ui != null) {
ui.dispose();
world.dispose();
}
-
+
world = new World();
-
- if(baseFolder != null) {
- EngineAssetManager.setAssetFolder(baseFolder);
- Config.load();
- }
-
+
+ EngineAssetManager.setAssetFolder(baseFolder);
+ Config.getInstance().load();
+
try {
world.loadWorldDesc();
} catch (Exception e) {
@@ -98,22 +97,24 @@ public void loadGame(String baseFolder) {
EngineLogger.error("EXITING: " + e.getMessage());
Gdx.app.exit();
}
-
+
ui = new UI(world);
}
@Override
public void create() {
if (!debug)
- debug = Config.getProperty(Config.DEBUG_PROP, debug);
+ debug = Config.getInstance().getProperty(Config.DEBUG_PROP, debug);
if (debug)
EngineLogger.setDebug();
+ else
+ EngineLogger.setDebugLevel(Application.LOG_ERROR);
EngineLogger.debug("GAME CREATE");
if (forceRes == null)
- forceRes = Config.getProperty(Config.FORCE_RES_PROP, forceRes);
+ forceRes = Config.getInstance().getProperty(Config.FORCE_RES_PROP, forceRes);
if (forceRes != null) {
EngineAssetManager.getInstance().forceResolution(forceRes);
@@ -123,10 +124,10 @@ public void create() {
if (EngineLogger.debugMode()) {
if (chapter == null)
- chapter = Config.getProperty(Config.CHAPTER_PROP, chapter);
+ chapter = Config.getInstance().getProperty(Config.CHAPTER_PROP, chapter);
if (testScene == null) {
- testScene = Config.getProperty(Config.TEST_SCENE_PROP, testScene);
+ testScene = Config.getInstance().getProperty(Config.TEST_SCENE_PROP, testScene);
}
if (testScene != null || chapter != null) {
@@ -142,7 +143,7 @@ public void create() {
}
if (gameState == null)
- gameState = Config.getProperty(Config.LOAD_GAMESTATE_PROP, gameState);
+ gameState = Config.getInstance().getProperty(Config.LOAD_GAMESTATE_PROP, gameState);
if (gameState != null) {
try {
@@ -155,7 +156,7 @@ public void create() {
if (restart) {
try {
world.getSerializer().loadChapter();
-
+
ui.setCurrentScreen(UI.Screens.SCENE_SCREEN);
} catch (Exception e) {
EngineLogger.error("ERROR LOADING GAME", e);
@@ -165,13 +166,13 @@ public void create() {
}
if (recordName == null)
- recordName = Config.getProperty(Config.PLAY_RECORD_PROP, recordName);
+ recordName = Config.getInstance().getProperty(Config.PLAY_RECORD_PROP, recordName);
if (recordName != null) {
ui.getRecorder().setFilename(recordName);
ui.getRecorder().load();
ui.getRecorder().setPlaying(true);
-
+
ui.setCurrentScreen(UI.Screens.SCENE_SCREEN);
}
}
@@ -185,9 +186,6 @@ public void create() {
EngineLogger.debug("Density: " + Gdx.graphics.getDensity());
EngineLogger.debug("Size Multiplier: " + DPIUtils.getSizeMultiplier());
}
-
- // Capture back key
- Gdx.input.setCatchBackKey(true);
}
@Override
@@ -210,8 +208,8 @@ public void render() {
@Override
public void resize(int width, int height) {
EngineLogger.debug(MessageFormat.format("GAME RESIZE {0}x{1}", width, height));
-
- if(ui != null)
+
+ if (ui != null)
ui.resize(width, height);
}
@@ -220,8 +218,7 @@ public void pause() {
boolean bot = ui.getTesterBot().isEnabled();
boolean r = ui.getRecorder().isPlaying();
- if (!world.isDisposed() &&
- ((!bot && !r) || EngineLogger.lastError != null)) {
+ if (!world.isDisposed() && ((!bot && !r) || EngineLogger.lastError != null)) {
EngineLogger.debug("GAME PAUSE");
ui.pause();
try {
diff --git a/blade-engine/src/com/bladecoder/engine/actions/ActionFactory.java b/blade-engine/src/com/bladecoder/engine/actions/ActionFactory.java
index ea9531a9e..e2cc8d7b4 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/ActionFactory.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/ActionFactory.java
@@ -17,6 +17,7 @@
import java.util.HashMap;
+import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import com.badlogic.gdx.utils.reflect.ReflectionException;
import com.bladecoder.engine.util.ActionUtils;
@@ -25,20 +26,95 @@
public class ActionFactory {
private static ClassLoader loader = ActionFactory.class.getClassLoader();
+ private static ObjectMap> tagToClass = new ObjectMap<>();
+
+ static {
+ addClassTag(AlphaAnimAction.class);
+ addClassTag(AnimationAction.class);
+ addClassTag(CameraAction.class);
+ addClassTag(CancelVerbAction.class);
+ addClassTag(ChooseAction.class);
+ addClassTag(CommentAction.class);
+ addClassTag(DisableActionAction.class);
+ addClassTag(DropItemAction.class);
+ addClassTag(EndAction.class);
+ addClassTag(EndGameAction.class);
+ addClassTag(GotoAction.class);
+ addClassTag(IfAttrAction.class);
+ addClassTag(IfInkVariableAction.class);
+ addClassTag(IfPropertyAction.class);
+ addClassTag(IfSceneAttrAction.class);
+ addClassTag(InkNewStoryAction.class);
+ addClassTag(InkRunAction.class);
+ addClassTag(InkVariable.class);
+ addClassTag(LeaveAction.class);
+ addClassTag(LoadChapterAction.class);
+ addClassTag(LookAtAction.class);
+ addClassTag(MoveToSceneAction.class);
+ addClassTag(MusicAction.class);
+ addClassTag(MusicVolumeAction.class);
+ addClassTag(OpenURLAction.class);
+ addClassTag(PickUpAction.class);
+ addClassTag(PlaySoundAction.class);
+ addClassTag(PositionAction.class);
+ addClassTag(PositionAnimAction.class);
+ addClassTag(PropertyAction.class);
+ addClassTag(RandomPositionAction.class);
+ addClassTag(RemoveInventoryItemAction.class);
+ addClassTag(RepeatAction.class);
+ addClassTag(RotateAction.class);
+ addClassTag(RunOnceAction.class);
+ addClassTag(RunVerbAction.class);
+ addClassTag(SayAction.class);
+ addClassTag(SayDialogAction.class);
+ addClassTag(ScaleAction.class);
+ addClassTag(ScaleAnimActionXY.class);
+ addClassTag(ScreenPositionAction.class);
+ addClassTag(SetAchievementAction.class);
+ addClassTag(SetActorAttrAction.class);
+ addClassTag(SetCutmodeAction.class);
+ addClassTag(SetDialogOptionAttrAction.class);
+ addClassTag(SetPlayerAction.class);
+ addClassTag(SetSceneStateAction.class);
+ addClassTag(SetStateAction.class);
+ addClassTag(SetDescAction.class);
+ addClassTag(SetWalkzoneAction.class);
+ addClassTag(ShowInventoryAction.class);
+ addClassTag(SoundAction.class);
+ addClassTag(TalktoAction.class);
+ addClassTag(TextAction.class);
+ addClassTag(TintAnimAction.class);
+ addClassTag(TransitionAction.class);
+ addClassTag(WaitAction.class);
+ }
+
+ private static void addClassTag(Class extends Action> cls) {
+ tagToClass.put(ActionUtils.getName(cls), cls);
+ }
+
+ public static ObjectMap> getClassTags() {
+ return tagToClass;
+ }
public static void setActionClassLoader(ClassLoader loader) {
ActionFactory.loader = loader;
}
-
+
public static ClassLoader getActionClassLoader() {
return loader;
}
- public static Action createByClass(String className, HashMap params) throws ClassNotFoundException, ReflectionException {
+ public static Action create(String tag, HashMap params)
+ throws ClassNotFoundException, ReflectionException {
Action a = null;
- Class> c = Class.forName(className, true, loader);
+ Class> c = tagToClass.get(tag);
+
+ if (c == null) {
+ c = Class.forName(tag, true, loader);
+ }
+
a = (Action) ClassReflection.newInstance(c);
if (params != null) {
@@ -48,9 +124,10 @@ public static Action createByClass(String className, HashMap par
try {
ActionUtils.setParam(a, key, value);
- } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
- EngineLogger.error("Error Setting Action Param - Action:" + className + " Param: " + key
- + " Value: " + value + " Msg: NOT FOUND " + e.getMessage());
+ } catch (NoSuchFieldException | SecurityException | IllegalArgumentException
+ | IllegalAccessException e) {
+ EngineLogger.error("Error Setting Action Param - Action:" + tag + " Param: " + key + " Value: "
+ + value + " Msg: NOT FOUND " + e.getMessage());
}
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/BaseCallbackAction.java b/blade-engine/src/com/bladecoder/engine/actions/BaseCallbackAction.java
index 6d5f0593d..8cc74ad5b 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/BaseCallbackAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/BaseCallbackAction.java
@@ -18,6 +18,7 @@
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.Json.Serializable;
import com.badlogic.gdx.utils.JsonValue;
+import com.bladecoder.engine.model.Scene;
import com.bladecoder.engine.model.World;
import com.bladecoder.engine.serialization.ActionCallbackSerializer;
import com.bladecoder.engine.serialization.BladeJson;
@@ -32,9 +33,9 @@ public abstract class BaseCallbackAction implements Action, ActionCallback, Seri
@ActionProperty(required = true)
@ActionPropertyDescription("If this param is 'false' the text is showed and the action continues inmediatly")
private boolean wait = true;
-
+
protected World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -45,7 +46,7 @@ public void resume() {
if (verbCb != null || sCb != null) {
if (verbCb == null) {
- verbCb = ActionCallbackSerializer.find(w, sCb);
+ verbCb = ActionCallbackSerializer.find(w, w.getCurrentScene(), sCb);
}
ActionCallback cb2 = verbCb;
@@ -70,8 +71,11 @@ public boolean getWait() {
@Override
public void write(Json json) {
- if(verbCb != null)
- json.writeValue("cb", ActionCallbackSerializer.find(((BladeJson) json).getWorld(), verbCb));
+ if (verbCb != null) {
+ World w = ((BladeJson) json).getWorld();
+ Scene s = ((BladeJson) json).getScene();
+ json.writeValue("cb", ActionCallbackSerializer.find(w, s, verbCb));
+ }
}
@Override
diff --git a/blade-engine/src/com/bladecoder/engine/actions/CameraAction.java b/blade-engine/src/com/bladecoder/engine/actions/CameraAction.java
index dc81c4f3b..c2fcce5d5 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/CameraAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/CameraAction.java
@@ -31,7 +31,7 @@ public class CameraAction implements Action {
@ActionPropertyDescription("Sets the camera position relative to this actor.")
@ActionProperty(type = Type.ACTOR)
private String target;
-
+
@ActionProperty
@ActionPropertyDescription("The target position")
private Vector2 pos;
@@ -47,7 +47,7 @@ public class CameraAction implements Action {
@ActionPropertyDescription("Sets the actor to follow. 'none' puts no actor to follow")
@ActionProperty(type = Type.ACTOR)
private String followActor;
-
+
@ActionProperty
@ActionPropertyDescription("The interpolation mode")
private InterpolationMode interpolation;
@@ -55,9 +55,9 @@ public class CameraAction implements Action {
@ActionProperty(defaultValue = "true", required = true)
@ActionPropertyDescription("If this param is 'false' the text is showed and the action continues inmediatly")
private boolean wait = true;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -65,53 +65,55 @@ public void init(World w) {
@Override
public boolean run(VerbRunner cb) {
-
+
Vector2 pos2 = null;
-
+
Float zoom2 = zoom;
-
- if(pos != null)
+
+ if (pos != null)
pos2 = new Vector2(pos);
float scale = EngineAssetManager.getInstance().getScale();
SceneCamera camera = w.getSceneCamera();
-
- if(zoom2 == null || zoom2 < 0)
+
+ if (zoom2 == null || zoom2 < 0)
zoom2 = camera.getZoom();
-
- if(pos == null && target == null) {
+
+ if (pos == null && target == null) {
pos2 = new Vector2(camera.getPosition());
pos2.x /= scale;
pos2.y /= scale;
}
-
+
if (target != null) {
BaseActor target = w.getCurrentScene().getActor(this.target, false);
-
+
float x = target.getX();
float y = target.getY();
-
- if(target instanceof InteractiveActor) {
+
+ if (target instanceof InteractiveActor) {
Vector2 refPoint = ((InteractiveActor) target).getRefPoint();
- x+= refPoint.x;
- y+= refPoint.y;
+ x += refPoint.x;
+ y += refPoint.y;
}
-
- if(pos2 != null){
+
+ if (pos2 != null) {
pos2.x += x;
pos2.y += y;
} else {
- pos2 = new Vector2(x,y);
+ pos2 = new Vector2(x, y);
}
- }
+ }
+
+ camera.stopAnim();
if (followActor != null) {
if (followActor.equals("none"))
w.getCurrentScene().setCameraFollowActor(null);
else {
- w.getCurrentScene().setCameraFollowActor((SpriteActor) w.getCurrentScene()
- .getActor(followActor, false));
+ w.getCurrentScene()
+ .setCameraFollowActor((SpriteActor) w.getCurrentScene().getActor(followActor, false));
}
}
@@ -120,9 +122,9 @@ public boolean run(VerbRunner cb) {
camera.setPosition(pos2.x * scale, pos2.y * scale);
return false;
} else {
- camera.startAnimation(pos2.x * scale, pos2.y * scale, zoom2, duration, interpolation, wait?cb:null);
+ camera.startAnimation(pos2.x * scale, pos2.y * scale, zoom2, duration, interpolation, wait ? cb : null);
}
-
+
return wait;
}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/DropItemAction.java b/blade-engine/src/com/bladecoder/engine/actions/DropItemAction.java
index 35b0f6be5..b2755e44b 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/DropItemAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/DropItemAction.java
@@ -22,6 +22,7 @@
import com.bladecoder.engine.actions.Param.Type;
import com.bladecoder.engine.assets.EngineAssetManager;
import com.bladecoder.engine.model.BaseActor;
+import com.bladecoder.engine.model.Inventory;
import com.bladecoder.engine.model.Scene;
import com.bladecoder.engine.model.VerbRunner;
import com.bladecoder.engine.model.World;
@@ -40,9 +41,13 @@ public class DropItemAction implements Action {
@ActionProperty
@ActionPropertyDescription("Position in the scene where de actor is dropped")
private Vector2 pos;
-
+
+ @ActionProperty
+ @ActionPropertyDescription("Inventory name. If empty, the active inventory is used.")
+ private String inventory;
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -57,36 +62,47 @@ public boolean run(VerbRunner cb) {
else
ts = w.getScene(scene);
-
+ Inventory inv = null;
+
+ if (inventory == null) {
+ inv = w.getInventory();
+ } else {
+ inv = w.getInventories().get(inventory);
+ if (inv == null) {
+ EngineLogger.error("Inventory not found: " + inventory);
+ return false;
+ }
+ }
+
BaseActor a;
-
+
if (actor != null) {
- a = w.getInventory().get(actor);
+ a = inv.get(actor);
if (a == null) {
EngineLogger.error(MessageFormat.format("DropItemAction - Item not found: {0}", actor));
return false;
}
- removeActor(ts, a);
+ removeActor(inv, ts, a);
} else {
- int n = w.getInventory().getNumItems();
-
- for(int i = n - 1; i >= 0; i--) {
- a = w.getInventory().get(i);
-
- removeActor(ts, a);
+ int n = inv.getNumItems();
+
+ for (int i = n - 1; i >= 0; i--) {
+ a = inv.get(i);
+
+ removeActor(inv, ts, a);
}
}
return false;
}
- private void removeActor(Scene ts, BaseActor a) {
+ private void removeActor(Inventory inv, Scene ts, BaseActor a) {
float scale = EngineAssetManager.getInstance().getScale();
- w.getInventory().removeItem(a.getId());
+ inv.removeItem(a.getId());
if (ts != w.getCurrentScene() && w.getCachedScene(ts.getId()) == null && a instanceof Disposable)
((Disposable) a).dispose();
diff --git a/blade-engine/src/com/bladecoder/engine/actions/GotoAction.java b/blade-engine/src/com/bladecoder/engine/actions/GotoAction.java
index 80e677162..44d2ad52d 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/GotoAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/GotoAction.java
@@ -24,6 +24,7 @@
import com.bladecoder.engine.model.InteractiveActor;
import com.bladecoder.engine.model.VerbRunner;
import com.bladecoder.engine.model.World;
+import com.bladecoder.engine.util.EngineLogger;
@ActionDescription("Walks to the selected position")
public class GotoAction implements Action {
@@ -32,27 +33,27 @@ public enum Align {
}
@ActionPropertyDescription("The walking actor")
- @ActionProperty(type = Type.CHARACTER_ACTOR, required=true)
+ @ActionProperty(type = Type.CHARACTER_ACTOR, required = true)
private String actor;
@ActionPropertyDescription("Walks to this actor")
@ActionProperty(type = Type.ACTOR)
private String target;
-
+
@ActionProperty
@ActionPropertyDescription("The absolute position to walk to if no target actor is selected. Relative to target if selected.")
private Vector2 pos;
-
- @ActionProperty(required=true, defaultValue = "false")
+
+ @ActionProperty(required = true, defaultValue = "false")
@ActionPropertyDescription("Ignore the walking zone and walk in a straight line.")
private boolean ignoreWalkZone = false;
@ActionProperty(required = true, defaultValue = "true")
@ActionPropertyDescription("If this param is 'false' the text is showed and the action continues inmediatly")
private boolean wait = true;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -62,35 +63,40 @@ public void init(World w) {
public boolean run(VerbRunner cb) {
CharacterActor actor = (CharacterActor) w.getCurrentScene().getActor(this.actor, false);
-
+
float x = actor.getX();
float y = actor.getY();
if (target != null) {
- BaseActor target = w.getCurrentScene().getActor(this.target, false);
-
- x = target.getX();
- y = target.getY();
-
- if(target instanceof InteractiveActor && target != actor) {
- Vector2 refPoint = ((InteractiveActor) target).getRefPoint();
- x+= refPoint.x;
- y+= refPoint.y;
+ BaseActor targetActor = w.getCurrentScene().getActor(target, false);
+
+ if (targetActor == null) {
+ EngineLogger.error(target + " not found in the current scene.");
+ return false;
}
-
- if(pos != null){
+
+ x = targetActor.getX();
+ y = targetActor.getY();
+
+ if (targetActor instanceof InteractiveActor && targetActor != actor) {
+ Vector2 refPoint = ((InteractiveActor) targetActor).getRefPoint();
+ x += refPoint.x;
+ y += refPoint.y;
+ }
+
+ if (pos != null) {
float scale = EngineAssetManager.getInstance().getScale();
-
+
x += pos.x * scale;
y += pos.y * scale;
}
- } else if(pos != null){
+ } else if (pos != null) {
float scale = EngineAssetManager.getInstance().getScale();
-
+
x = pos.x * scale;
y = pos.y * scale;
}
-
+
actor.goTo(new Vector2(x, y), wait ? cb : null, ignoreWalkZone);
return wait;
diff --git a/blade-engine/src/com/bladecoder/engine/actions/IAchievementAPI.java b/blade-engine/src/com/bladecoder/engine/actions/IAchievementAPI.java
new file mode 100644
index 000000000..13a9ce543
--- /dev/null
+++ b/blade-engine/src/com/bladecoder/engine/actions/IAchievementAPI.java
@@ -0,0 +1,7 @@
+package com.bladecoder.engine.actions;
+
+public interface IAchievementAPI {
+
+ void setAchievement(String name);
+
+}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/IfAttrAction.java b/blade-engine/src/com/bladecoder/engine/actions/IfAttrAction.java
index 7e962ac21..2db2a3b53 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/IfAttrAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/IfAttrAction.java
@@ -18,19 +18,21 @@
import com.bladecoder.engine.model.AnimationRenderer;
import com.bladecoder.engine.model.BaseActor;
import com.bladecoder.engine.model.InteractiveActor;
+import com.bladecoder.engine.model.Inventory;
import com.bladecoder.engine.model.Scene;
import com.bladecoder.engine.model.SpriteActor;
import com.bladecoder.engine.model.VerbRunner;
import com.bladecoder.engine.model.World;
import com.bladecoder.engine.util.ActionUtils;
import com.bladecoder.engine.util.EngineLogger;
+import com.bladecoder.engine.util.PolygonUtils;
@ActionDescription(name = "IfActorAttr", value = "Execute the actions inside the If/EndIf if the attribute has the specified value.")
public class IfAttrAction extends AbstractIfAction {
public static final String ENDTYPE_VALUE = "else";
public enum ActorAttribute {
- STATE, VISIBLE, INTERACTIVE, IN_INVENTORY, TARGET, IN_SCENE, LAYER, DIRECTION, IN_UI
+ STATE, VISIBLE, INTERACTIVE, IN_INVENTORY, TARGET, IN_SCENE, LAYER, DIRECTION, IN_UI, INSIDE
}
@ActionProperty(required = true)
@@ -57,25 +59,36 @@ public boolean run(VerbRunner cb) {
Scene s = actor.getScene(w);
final String actorId = actor.getActorId();
- if (actorId == null) {
- // if called inside a scene verb and no actor is specified, return
- EngineLogger.error(getClass() + ": No actor specified");
- return false;
- }
- BaseActor a = s.getActor(actorId, true);
+ if (attr.equals(ActorAttribute.STATE)) {
+ BaseActor a = s.getActor(actorId, true);
+ if (a == null || !(a instanceof InteractiveActor)) {
+ EngineLogger.error(getClass() + "- Actor not found: " + actorId);
+ return false;
+ }
- if (attr.equals(ActorAttribute.STATE) && a instanceof InteractiveActor) {
InteractiveActor ia = (InteractiveActor) a;
if (!ActionUtils.compareNullStr(value, ia.getState())) {
gotoElse(cb);
}
} else if (attr.equals(ActorAttribute.VISIBLE)) {
+ BaseActor a = s.getActor(actorId, true);
+ if (a == null) {
+ EngineLogger.error(getClass() + "- Actor not found: " + actorId);
+ return false;
+ }
+
boolean val = Boolean.parseBoolean(value);
if (val != a.isVisible()) {
gotoElse(cb);
}
} else if (attr.equals(ActorAttribute.INTERACTIVE)) {
+ BaseActor a = s.getActor(actorId, true);
+ if (a == null) {
+ EngineLogger.error(getClass() + "- Actor not found: " + actorId);
+ return false;
+ }
+
boolean val = Boolean.parseBoolean(value);
if (a instanceof InteractiveActor) {
@@ -86,12 +99,25 @@ public boolean run(VerbRunner cb) {
gotoElse(cb);
}
} else if (attr.equals(ActorAttribute.IN_INVENTORY)) {
- boolean val = Boolean.parseBoolean(value);
+ // 'value' can have the inventory name to search in
+ // or 'true/false' to search in the current inventory.
+
+ Inventory inventory = null;
+ boolean val = true;
+
+ if (value != null) {
+ inventory = w.getInventories().get(value);
+ }
+
+ if (inventory == null) {
+ // boolean mode: search in the current inventory
+ val = Boolean.parseBoolean(value);
+ inventory = w.getInventory();
+ }
SpriteActor item = null;
- if (a != null)
- item = w.getInventory().get(a.getId());
+ item = inventory.get(actorId);
if ((val && item == null) || (!val && item != null)) {
gotoElse(cb);
@@ -115,12 +141,25 @@ public boolean run(VerbRunner cb) {
if ((val && a2 == null) || (!val && a2 != null))
gotoElse(cb);
- } else if (attr.equals(ActorAttribute.LAYER) && a instanceof InteractiveActor) {
+ } else if (attr.equals(ActorAttribute.LAYER)) {
+ BaseActor a = s.getActor(actorId, true);
+ if (a == null || !(a instanceof InteractiveActor)) {
+ EngineLogger.error(getClass() + "- No not found: " + actorId);
+ return false;
+ }
+
InteractiveActor ia = (InteractiveActor) a;
if (!ActionUtils.compareNullStr(value, ia.getLayer())) {
gotoElse(cb);
}
- } else if (attr.equals(ActorAttribute.DIRECTION) && a instanceof SpriteActor) {
+ } else if (attr.equals(ActorAttribute.DIRECTION)) {
+
+ BaseActor a = s.getActor(actorId, true);
+ if (a == null || !(a instanceof SpriteActor)) {
+ EngineLogger.error(getClass() + "- No not found: " + actorId);
+ return false;
+ }
+
SpriteActor sa = (SpriteActor) a;
if (sa.getRenderer() instanceof AnimationRenderer) {
@@ -136,6 +175,25 @@ public boolean run(VerbRunner cb) {
gotoElse(cb);
}
}
+ } else if (attr.equals(ActorAttribute.INSIDE)) {
+ BaseActor a = s.getActor(actorId, true);
+ if (a == null) {
+ EngineLogger.error(getClass() + "- No not found: " + actorId);
+ return false;
+ }
+
+ BaseActor insideActor = w.getCurrentScene().getActor(value, false);
+
+ if (insideActor == null) {
+ EngineLogger.debug("Actor for inside test not found: " + value);
+ return false;
+ }
+
+ boolean inside = PolygonUtils.isPointInside(insideActor.getBBox(), a.getX(), a.getY(), true);
+
+ if (!inside) {
+ gotoElse(cb);
+ }
}
return false;
diff --git a/blade-engine/src/com/bladecoder/engine/actions/IfPropertyAction.java b/blade-engine/src/com/bladecoder/engine/actions/IfPropertyAction.java
index 56516ff05..5dbdbb9ac 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/IfPropertyAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/IfPropertyAction.java
@@ -20,7 +20,7 @@
import com.bladecoder.engine.util.ActionUtils;
import com.bladecoder.engine.util.Config;
-@ActionDescription("Execute actions inside the If/EndIf if the game property has the specified value. Properties are created with the 'Property' action or set in the 'BladeEngine.properties' file. The next always exists: SAVED_GAME_VERSION, PREVIOUS_SCENE, CURRENT_CHAPTER, PLATFORM")
+@ActionDescription("Execute actions inside the If/EndIf if the game property has the specified value. Properties are created with the 'Property' action or set in the 'BladeEngine.properties' file. The next always exists: SAVED_GAME_VERSION, PREVIOUS_SCENE, CURRENT_CHAPTER, PLATFORM.")
public class IfPropertyAction extends AbstractIfAction {
@ActionProperty(required = true)
@ActionPropertyDescription("The property name")
@@ -29,9 +29,9 @@ public class IfPropertyAction extends AbstractIfAction {
@ActionProperty
@ActionPropertyDescription("The property value")
private String value;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -40,12 +40,15 @@ public void init(World w) {
@Override
public boolean run(VerbRunner cb) {
String valDest = w.getCustomProperty(name);
-
- if(valDest == null)
- valDest = Config.getProperty(name, null);
-
+
+ if (valDest == null)
+ valDest = Config.getInstance().getProperty(name, null);
+
+ if (valDest == null)
+ valDest = Config.getInstance().getPref(name, null);
+
if (!ActionUtils.compareNullStr(value, valDest)) {
- gotoElse((VerbRunner) cb);
+ gotoElse(cb);
}
return false;
diff --git a/blade-engine/src/com/bladecoder/engine/actions/IfSceneAttrAction.java b/blade-engine/src/com/bladecoder/engine/actions/IfSceneAttrAction.java
index 2a2db5009..665f0ba13 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/IfSceneAttrAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/IfSceneAttrAction.java
@@ -40,9 +40,9 @@ public enum SceneAttr {
@ActionProperty
@ActionPropertyDescription("The attribute value")
private String value;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -50,27 +50,27 @@ public void init(World w) {
@Override
public boolean run(VerbRunner cb) {
- Scene s = (scene != null && !scene.isEmpty()) ? w.getScene(scene) : w
- .getCurrentScene();
+ Scene s = (scene != null && !scene.isEmpty()) ? w.getScene(scene) : w.getCurrentScene();
if (attr == SceneAttr.STATE) {
if (!ActionUtils.compareNullStr(value, s.getState())) {
- gotoElse((VerbRunner) cb);
+ gotoElse(cb);
}
} else if (attr == SceneAttr.CURRENT_SCENE) {
String scn = w.getCurrentScene().getId();
-
- if (!ActionUtils.compareNullStr(value, scn)) {
- gotoElse((VerbRunner) cb);
+
+ if (((value != null && !value.isEmpty()) && !ActionUtils.compareNullStr(value, scn))
+ || (scene != null && !scene.isEmpty() && !ActionUtils.compareNullStr(s.getId(), scn))) {
+ gotoElse(cb);
}
} else if (attr == SceneAttr.PLAYER) {
CharacterActor player = s.getPlayer();
-
- String id = player!=null?player.getId():null;
-
+
+ String id = player != null ? player.getId() : null;
+
if (!ActionUtils.compareNullStr(value, id)) {
- gotoElse((VerbRunner) cb);
- }
+ gotoElse(cb);
+ }
}
return false;
diff --git a/blade-engine/src/com/bladecoder/engine/actions/LeaveAction.java b/blade-engine/src/com/bladecoder/engine/actions/LeaveAction.java
index c93f0b1a7..69f590436 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/LeaveAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/LeaveAction.java
@@ -24,13 +24,17 @@ public class LeaveAction implements Action {
@ActionPropertyDescription("The target scene")
@ActionProperty(type = Type.SCENE, required = true)
private String scene;
-
+
@ActionPropertyDescription("Inits the scene and run the 'init' verb")
@ActionProperty(defaultValue = "true", required = true)
private boolean init = true;
-
+
+ @ActionPropertyDescription("The verb to run after loading. If null, 'init' verb will be run but only if init=true")
+ @ActionProperty
+ private String initVerb = null;
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -38,7 +42,7 @@ public void init(World w) {
@Override
public boolean run(VerbRunner cb) {
- w.setCurrentScene(scene, init);
+ w.setCurrentScene(scene, init, initVerb);
return true;
}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/MoveToSceneAction.java b/blade-engine/src/com/bladecoder/engine/actions/MoveToSceneAction.java
index 674f71532..0ccec89dd 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/MoveToSceneAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/MoveToSceneAction.java
@@ -19,7 +19,7 @@
import com.bladecoder.engine.actions.Param.Type;
import com.bladecoder.engine.assets.AssetConsumer;
import com.bladecoder.engine.assets.EngineAssetManager;
-import com.bladecoder.engine.model.InteractiveActor;
+import com.bladecoder.engine.model.BaseActor;
import com.bladecoder.engine.model.Scene;
import com.bladecoder.engine.model.VerbRunner;
import com.bladecoder.engine.model.World;
@@ -27,60 +27,68 @@
@ActionDescription("Move the actor to the selected scene")
public class MoveToSceneAction implements Action {
- @ActionProperty(required=true)
- @ActionPropertyDescription("The selected actor")
+ @ActionProperty(required = true)
+ @ActionPropertyDescription("The selected actor")
private SceneActorRef actor;
@ActionPropertyDescription("The target scene. The current scene if empty.")
@ActionProperty(type = Type.SCENE)
private String scene;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
}
@Override
- public boolean run(VerbRunner cb) {
+ public boolean run(VerbRunner cb) {
final Scene s = actor.getScene(w);
- final String actorId = actor.getActorId();
-
+ final String actorId = actor.getActorId();
+
if (actorId == null) {
// if called in a scene verb and no actor is specified, we do nothing
EngineLogger.error(getClass() + ": No actor specified");
return false;
}
- InteractiveActor a = (InteractiveActor)s.getActor(actorId, false);
+ BaseActor a = s.getActor(actorId, false);
+
+ if (a == null) {
+ EngineLogger.error(getClass() + "- Actor not found: " + actorId + " in scene: " + s.getId());
+ return false;
+ }
s.removeActor(a);
-
- if(s == w.getCurrentScene() && a instanceof Disposable)
- ((Disposable) a).dispose();
-
- Scene ts = null;
-
- if(scene == null)
+
+ Scene ts = null;
+
+ if (scene == null)
ts = w.getCurrentScene();
else
ts = w.getScene(scene);
-
+
+ // Dispose if s is the current scene or a cached scene and the target is not the
+ // current scene or a cache scene
+ if ((s == w.getCurrentScene() || w.getCachedScene(ts.getId()) != null)
+ && !(ts == w.getCurrentScene() || w.getCachedScene(ts.getId()) != null) && a instanceof Disposable) {
+ ((Disposable) a).dispose();
+ }
+
// We must load assets when the target scene is the current scene or when
// the scene is cached.
- if((ts == w.getCurrentScene() ||
- w.getCachedScene(ts.getId()) != null) && a instanceof AssetConsumer) {
+ if ((ts == w.getCurrentScene() || w.getCachedScene(ts.getId()) != null)
+ && !(s == w.getCurrentScene() || w.getCachedScene(s.getId()) != null) && a instanceof AssetConsumer) {
((AssetConsumer) a).loadAssets();
EngineAssetManager.getInstance().finishLoading();
((AssetConsumer) a).retrieveAssets();
}
-
+
ts.addActor(a);
-
+
return false;
}
-
}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/PickUpAction.java b/blade-engine/src/com/bladecoder/engine/actions/PickUpAction.java
index b3d1a8fa6..de1031534 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/PickUpAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/PickUpAction.java
@@ -19,6 +19,7 @@
import com.bladecoder.engine.assets.EngineAssetManager;
import com.bladecoder.engine.model.AnimationRenderer;
import com.bladecoder.engine.model.InteractiveActor;
+import com.bladecoder.engine.model.Inventory;
import com.bladecoder.engine.model.Scene;
import com.bladecoder.engine.model.SpriteActor;
import com.bladecoder.engine.model.VerbRunner;
@@ -34,9 +35,13 @@ public class PickUpAction implements Action {
@ActionProperty
@ActionPropertyDescription("The animation/sprite to show while in inventory. If empty, the animation will be 'actorid.inventory'")
private String animation;
-
+
+ @ActionProperty
+ @ActionPropertyDescription("Inventory name. If empty, the active inventory is used.")
+ private String inventory;
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -57,10 +62,8 @@ public boolean run(VerbRunner cb) {
if (actor instanceof SpriteActor) {
SpriteActor a = (SpriteActor) actor;
-
- if (scn != w.getCurrentScene() &&
- w.getCachedScene(scn.getId()) == null
- ) {
+
+ if (scn != w.getCurrentScene() && w.getCachedScene(scn.getId()) == null) {
a.loadAssets();
EngineAssetManager.getInstance().finishLoading();
a.retrieveAssets();
@@ -73,7 +76,19 @@ else if (((AnimationRenderer) a.getRenderer()).getAnimations().get(a.getId() + "
a.startAnimation(a.getId() + ".inventory", null);
}
- w.getInventory().addItem(a);
+ Inventory inv = null;
+
+ if (inventory == null) {
+ inv = w.getInventory();
+ } else {
+ inv = w.getInventories().get(inventory);
+ if (inv == null) {
+ EngineLogger.error("Inventory not found: " + inventory);
+ return false;
+ }
+ }
+
+ inv.addItem(a);
}
return false;
diff --git a/blade-engine/src/com/bladecoder/engine/actions/PropertyAction.java b/blade-engine/src/com/bladecoder/engine/actions/PropertyAction.java
index 2310714ae..743fef4e8 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/PropertyAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/PropertyAction.java
@@ -22,16 +22,14 @@
public class PropertyAction implements Action {
@ActionProperty(required = true)
@ActionPropertyDescription("Property name")
-
private String prop;
- @ActionProperty(required = true)
+ @ActionProperty
@ActionPropertyDescription("Property value")
-
private String value;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
diff --git a/blade-engine/src/com/bladecoder/engine/actions/RandomPositionAction.java b/blade-engine/src/com/bladecoder/engine/actions/RandomPositionAction.java
new file mode 100644
index 000000000..5089916f3
--- /dev/null
+++ b/blade-engine/src/com/bladecoder/engine/actions/RandomPositionAction.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright 2014 Rafael Garcia Moreno.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package com.bladecoder.engine.actions;
+
+import com.badlogic.gdx.math.Vector2;
+import com.bladecoder.engine.assets.EngineAssetManager;
+import com.bladecoder.engine.model.BaseActor;
+import com.bladecoder.engine.model.InteractiveActor;
+import com.bladecoder.engine.model.Scene;
+import com.bladecoder.engine.model.VerbRunner;
+import com.bladecoder.engine.model.World;
+
+@ActionDescription("Sets actor position randomly.")
+public class RandomPositionAction implements Action {
+ @ActionProperty(required = true)
+ @ActionPropertyDescription("The actor to change his position")
+ private SceneActorRef actor;
+
+ @ActionProperty
+ @ActionPropertyDescription("Obtain the target position from this actor.")
+ private SceneActorRef target;
+
+ @ActionProperty(required = true)
+ @ActionPropertyDescription("Maximum xy values. The absolute position to set if no target is selected. Relative if target is selected.")
+ private Vector2 maxPosition;
+
+ @ActionProperty(required = true)
+ @ActionPropertyDescription("Minimum xy values. The absolute position to set if no target is selected. Relative if target is selected.")
+ private Vector2 minPosition;
+
+ private World w;
+
+ @Override
+ public void init(World w) {
+ this.w = w;
+ }
+
+ @Override
+ public boolean run(VerbRunner cb) {
+ Scene s = actor.getScene(w);
+
+ BaseActor a = s.getActor(actor.getActorId(), true);
+
+ float x = a.getX();
+ float y = a.getY();
+
+ float rx = (float) (minPosition.x + Math.random() * (maxPosition.x - minPosition.x));
+ float ry = (float) (minPosition.y + Math.random() * (maxPosition.y - minPosition.y));
+
+ if (target != null) {
+ Scene ts = target.getScene(w);
+ BaseActor anchorActor = ts.getActor(target.getActorId(), false);
+
+ x = anchorActor.getX();
+ y = anchorActor.getY();
+
+ if (anchorActor instanceof InteractiveActor && a != anchorActor) {
+ Vector2 refPoint = ((InteractiveActor) anchorActor).getRefPoint();
+ x += refPoint.x;
+ y += refPoint.y;
+ }
+
+ float scale = EngineAssetManager.getInstance().getScale();
+
+ x += rx * scale;
+ y += ry * scale;
+ } else {
+ float scale = EngineAssetManager.getInstance().getScale();
+ x = rx * scale;
+ y = ry * scale;
+ }
+
+ a.setPosition(x, y);
+
+ return false;
+ }
+
+}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/RotateAction.java b/blade-engine/src/com/bladecoder/engine/actions/RotateAction.java
index 326b99055..765912879 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/RotateAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/RotateAction.java
@@ -23,7 +23,7 @@
import com.bladecoder.engine.model.World;
import com.bladecoder.engine.util.InterpolationMode;
-@ActionDescription(name = "RotateAnim", value= "Sets an actor Rotate animation")
+@ActionDescription(name = "RotateAnim", value = "Sets an actor Rotate animation")
public class RotateAction implements Action {
@ActionPropertyDescription("The target actor")
@ActionProperty(type = Type.SPRITE_ACTOR)
@@ -52,24 +52,23 @@ public class RotateAction implements Action {
@ActionProperty
@ActionPropertyDescription("The interpolation mode")
private InterpolationMode interpolation;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
}
@Override
- public boolean run(VerbRunner cb) {
- SpriteActor a = (SpriteActor) w.getCurrentScene().getActor(actor, false);
-
+ public boolean run(VerbRunner cb) {
+ SpriteActor a = (SpriteActor) w.getCurrentScene().getActor(actor, true);
+
SpriteRotateTween t = new SpriteRotateTween();
- t.start(a, repeat, count, rotation, speed, interpolation,
- wait ? cb : null);
-
+ t.start(a, repeat, count, rotation, speed, interpolation, wait ? cb : null);
+
a.addTween(t);
-
+
return wait;
}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/RunVerbAction.java b/blade-engine/src/com/bladecoder/engine/actions/RunVerbAction.java
index 4decc1229..c5cea22c8 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/RunVerbAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/RunVerbAction.java
@@ -39,13 +39,13 @@ public class RunVerbAction implements VerbRunner, Action {
@ActionProperty
@ActionPropertyDescription("Aditional actor for 'use' verb")
private String target;
-
+
@ActionProperty(required = true)
@ActionPropertyDescription("If this param is 'false' the text is showed and the action continues inmediatly")
private boolean wait = true;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -53,19 +53,19 @@ public void init(World w) {
@Override
public boolean run(VerbRunner cb) {
-
- run(cb.getCurrentTarget(), wait?cb:null);
-
+
+ run(cb.getCurrentTarget(), wait ? cb : null);
+
return wait;
}
private Verb getVerb() {
Verb v = null;
-
+
Scene s = w.getCurrentScene();
if (actor != null) {
- InteractiveActor a = (InteractiveActor)s.getActor(actor, true);
+ InteractiveActor a = (InteractiveActor) s.getActor(actor, true);
v = a.getVerbManager().getVerb(verb, a.getState(), target);
}
@@ -78,8 +78,9 @@ private Verb getVerb() {
v = w.getVerbManager().getVerb(verb, null, target);
}
- if (v == null)
+ if (v == null) {
EngineLogger.error("Cannot find VERB: " + verb + " for ACTOR: " + actor);
+ }
return v;
}
@@ -91,16 +92,15 @@ public void resume() {
@Override
public void cancel() {
-
+
// check if the actor has been moved during the execution
- if(actor != null) {
- InteractiveActor a = (InteractiveActor)w.getCurrentScene().getActor(actor, true);
-
- if(a == null)
+ if (actor != null) {
+ InteractiveActor a = (InteractiveActor) w.getCurrentScene().getActor(actor, true);
+
+ if (a == null)
return;
}
-
-
+
getVerb().cancel();
}
@@ -114,9 +114,10 @@ public ArrayList getActions() {
Verb v = getVerb();
if (v == null) {
- if( actor != null)
- EngineLogger.error(MessageFormat.format("Verb ''{0}'' not found for actor ''{1}({3})'' and target ''{2}''.",
- verb, actor, target, ((InteractiveActor)w.getCurrentScene().getActor(actor, true)).getState()));
+ if (actor != null)
+ EngineLogger.error(MessageFormat.format(
+ "Verb ''{0}'' not found for actor ''{1}({3})'' and target ''{2}''.", verb, actor, target,
+ ((InteractiveActor) w.getCurrentScene().getActor(actor, true)).getState()));
else
EngineLogger.error(MessageFormat.format("Verb ''{0}'' not found.", verb));
@@ -129,8 +130,10 @@ public ArrayList getActions() {
@Override
public void run(String currentTarget, ActionCallback cb) {
Verb v = getVerb();
-
- v.run(currentTarget, cb);
+
+ if (v != null) {
+ v.run(currentTarget, cb);
+ }
}
@Override
@@ -141,6 +144,6 @@ public int getIP() {
@Override
public void setIP(int ip) {
getVerb().setIP(ip);
- }
+ }
}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/ScaleAction.java b/blade-engine/src/com/bladecoder/engine/actions/ScaleAction.java
index a85352ed3..e6b8ee3cd 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/ScaleAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/ScaleAction.java
@@ -23,7 +23,7 @@
import com.bladecoder.engine.model.World;
import com.bladecoder.engine.util.InterpolationMode;
-@ActionDescription(name = "ScaleAnim", value= "Proportional Scale animation for sprite actors")
+@ActionDescription(name = "ScaleAnim", value = "Proportional Scale animation for sprite actors")
public class ScaleAction implements Action {
@ActionPropertyDescription("The target actor")
@ActionProperty(type = Type.SPRITE_ACTOR)
@@ -39,37 +39,36 @@ public class ScaleAction implements Action {
@ActionProperty
@ActionPropertyDescription("The The times to repeat")
- private int count = 1;
+ private int count = -1;
@ActionProperty(required = true)
@ActionPropertyDescription("If this param is 'false' the transition is showed and the action continues inmediatly")
private boolean wait = true;
- @ActionProperty(required = true, defaultValue = "REPEAT")
+ @ActionProperty(required = true, defaultValue = "NO_REPEAT")
@ActionPropertyDescription("The repeat mode")
- private Tween.Type repeat = Tween.Type.REPEAT;
+ private Tween.Type repeat = Tween.Type.NO_REPEAT;
@ActionProperty
@ActionPropertyDescription("The interpolation mode")
private InterpolationMode interpolation;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
}
@Override
- public boolean run(VerbRunner cb) {
- SpriteActor a = (SpriteActor) w.getCurrentScene().getActor(actor, false);
-
+ public boolean run(VerbRunner cb) {
+ SpriteActor a = (SpriteActor) w.getCurrentScene().getActor(actor, true);
+
SpriteScaleTween t = new SpriteScaleTween();
- t.start(a, repeat, count, scale, scale, speed, interpolation,
- wait ? cb : null);
-
+ t.start(a, repeat, count, scale, scale, speed, interpolation, wait ? cb : null);
+
a.addTween(t);
-
+
return wait;
}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/ScaleAnimActionXY.java b/blade-engine/src/com/bladecoder/engine/actions/ScaleAnimActionXY.java
index d6078e67d..1215f3dd7 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/ScaleAnimActionXY.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/ScaleAnimActionXY.java
@@ -24,7 +24,7 @@
import com.bladecoder.engine.model.World;
import com.bladecoder.engine.util.InterpolationMode;
-@ActionDescription(name = "ScaleAnimXY", value= "Scale animation for sprite actors")
+@ActionDescription(name = "ScaleAnimXY", value = "Scale animation for sprite actors")
public class ScaleAnimActionXY implements Action {
@ActionPropertyDescription("The target actor")
@ActionProperty(type = Type.SPRITE_ACTOR)
@@ -53,24 +53,23 @@ public class ScaleAnimActionXY implements Action {
@ActionProperty
@ActionPropertyDescription("The interpolation mode")
private InterpolationMode interpolation;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
}
@Override
- public boolean run(VerbRunner cb) {
- SpriteActor a = (SpriteActor) w.getCurrentScene().getActor(actor, false);
-
+ public boolean run(VerbRunner cb) {
+ SpriteActor a = (SpriteActor) w.getCurrentScene().getActor(actor, true);
+
SpriteScaleTween t = new SpriteScaleTween();
- t.start(a, repeat, count, scale.x, scale.y, speed, interpolation,
- wait ? cb : null);
-
+ t.start(a, repeat, count, scale.x, scale.y, speed, interpolation, wait ? cb : null);
+
a.addTween(t);
-
+
return wait;
}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/ScreenPositionAction.java b/blade-engine/src/com/bladecoder/engine/actions/ScreenPositionAction.java
index d4beb0a75..0dd01ceaf 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/ScreenPositionAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/ScreenPositionAction.java
@@ -95,12 +95,9 @@ public boolean run(VerbRunner cb) {
v.y += viewport.getWorldHeight() / 2;
}
- // viewport.project(v);
-
v.x *= viewport.getScreenWidth() / viewport.getWorldWidth();
v.y *= viewport.getScreenHeight() / viewport.getWorldHeight();
- // v.y = viewport.getScreenHeight() - v.y;
v.y = Gdx.graphics.getHeight() - v.y;
if (w.getUIActors().getActors().contains(a))
diff --git a/blade-engine/src/com/bladecoder/engine/actions/SetAchievementAction.java b/blade-engine/src/com/bladecoder/engine/actions/SetAchievementAction.java
new file mode 100644
index 000000000..146e698da
--- /dev/null
+++ b/blade-engine/src/com/bladecoder/engine/actions/SetAchievementAction.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2014 Rafael Garcia Moreno.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package com.bladecoder.engine.actions;
+
+import com.bladecoder.engine.model.VerbRunner;
+import com.bladecoder.engine.model.World;
+
+@ActionDescription("Set an achievement.")
+public class SetAchievementAction implements Action {
+ public static IAchievementAPI achievementAPI;
+
+ @ActionProperty(required = true)
+ @ActionPropertyDescription("Achievement name")
+ private String name;
+
+ @Override
+ public void init(World w) {
+ }
+
+ @Override
+ public boolean run(VerbRunner cb) {
+ if (achievementAPI != null)
+ achievementAPI.setAchievement(name);
+
+ return false;
+ }
+
+}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/SetActorAttrAction.java b/blade-engine/src/com/bladecoder/engine/actions/SetActorAttrAction.java
index c06384096..7e9101708 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/SetActorAttrAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/SetActorAttrAction.java
@@ -60,7 +60,7 @@ public class SetActorAttrAction implements Action {
@ActionProperty
@ActionPropertyDescription("Sets the actor scale proportionally")
private Float scale;
-
+
@ActionProperty
@ActionPropertyDescription("Sets the actor scale non proportionally")
private Vector2 scaleXY;
@@ -91,13 +91,13 @@ public class SetActorAttrAction implements Action {
@ActionProperty
@ActionPropertyDescription("Sets the actor speed for walking. Only supported for character actors.")
private Float walkingSpeed;
-
+
@ActionProperty
@ActionPropertyDescription("Sets the position of the text when talking. Relative to the character position.")
private Vector2 talkingTextPos;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -163,7 +163,7 @@ public boolean run(VerbRunner cb) {
else
EngineLogger.error("'scale' property not supported for actor:" + a.getId());
}
-
+
if (scaleXY != null) {
if (a instanceof SpriteActor)
((SpriteActor) a).setScale(scaleXY.x, scaleXY.y);
@@ -180,7 +180,7 @@ public boolean run(VerbRunner cb) {
if (tint != null) {
if (a instanceof SpriteActor)
- ((SpriteActor) a).setTint(tint);
+ ((SpriteActor) a).setTint(tint.cpy());
else
EngineLogger.error("'tint' property not supported for actor:" + a.getId());
}
@@ -229,7 +229,7 @@ public boolean run(VerbRunner cb) {
} else
EngineLogger.error("'uiActor' property not supported for actor:" + a.getId());
}
-
+
if (talkingTextPos != null) {
if (a instanceof CharacterActor)
((CharacterActor) a).setTalkingTextPos(talkingTextPos);
@@ -244,8 +244,7 @@ private void setUIActor(Scene scn, InteractiveActor actor) {
scn.removeActor(actor);
- if (scn != w.getCurrentScene() && w.getCachedScene(scn.getId()) == null
- && actor instanceof AssetConsumer) {
+ if (scn != w.getCurrentScene() && w.getCachedScene(scn.getId()) == null && actor instanceof AssetConsumer) {
((AssetConsumer) actor).loadAssets();
EngineAssetManager.getInstance().finishLoading();
((AssetConsumer) actor).retrieveAssets();
diff --git a/blade-engine/src/com/bladecoder/engine/actions/SetDescAction.java b/blade-engine/src/com/bladecoder/engine/actions/SetDescAction.java
new file mode 100644
index 000000000..99e630f1a
--- /dev/null
+++ b/blade-engine/src/com/bladecoder/engine/actions/SetDescAction.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright 2014 Rafael Garcia Moreno.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package com.bladecoder.engine.actions;
+
+import com.bladecoder.engine.actions.Param.Type;
+import com.bladecoder.engine.model.InteractiveActor;
+import com.bladecoder.engine.model.Scene;
+import com.bladecoder.engine.model.VerbRunner;
+import com.bladecoder.engine.model.World;
+import com.bladecoder.engine.util.EngineLogger;
+
+@ActionDescription(value = "Sets the actor description")
+public class SetDescAction implements Action {
+ @ActionProperty(type = Type.SCENE_INTERACTIVE_ACTOR, required = true)
+ @ActionPropertyDescription("The target actor")
+ private SceneActorRef actor;
+
+ @ActionProperty
+ @ActionPropertyDescription("The actor 'desc'")
+ private String text;
+
+ private World w;
+
+ @Override
+ public void init(World w) {
+ this.w = w;
+ }
+
+ @Override
+ public boolean run(VerbRunner cb) {
+ final Scene s = actor.getScene(w);
+
+ String actorId = actor.getActorId();
+ if (actorId == null) {
+ EngineLogger.error("SetDesc - Actor not set.");
+ return false;
+ }
+
+ InteractiveActor a = (InteractiveActor) s.getActor(actorId, true);
+
+ if (a != null)
+ a.setDesc(text);
+ else
+ EngineLogger.error("SetDesc - Actor not found: " + actorId);
+
+ return false;
+ }
+
+}
diff --git a/blade-engine/src/com/bladecoder/engine/actions/SetPlayerAction.java b/blade-engine/src/com/bladecoder/engine/actions/SetPlayerAction.java
index 20d11de32..5e058aea4 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/SetPlayerAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/SetPlayerAction.java
@@ -19,6 +19,7 @@
import com.bladecoder.engine.assets.EngineAssetManager;
import com.bladecoder.engine.model.BaseActor;
import com.bladecoder.engine.model.CharacterActor;
+import com.bladecoder.engine.model.Inventory;
import com.bladecoder.engine.model.Scene;
import com.bladecoder.engine.model.VerbRunner;
import com.bladecoder.engine.model.World;
@@ -26,35 +27,38 @@
@ActionDescription("Sets the scene player")
public class SetPlayerAction implements Action {
- @ActionProperty(type = Type.SCENE_CHARACTER_ACTOR, required = true)
- @ActionPropertyDescription("The scene player")
+ @ActionProperty(type = Type.SCENE_CHARACTER_ACTOR)
+ @ActionPropertyDescription("The scene player")
private SceneActorRef actor;
-
+
@ActionProperty
- @ActionPropertyDescription("The inventory 'id' for the player. If empty, the inventory will not change.")
+ @ActionPropertyDescription("The inventory 'id' for the player. If empty, the inventory will not change.")
private String inventory;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
}
@Override
- public boolean run(VerbRunner cb) {
- Scene s = actor.getScene(w);
-
- BaseActor a = s.getActor(actor.getActorId(), true);
-
- s.setPlayer((CharacterActor)a);
-
- if(inventory != null) {
- w.getInventory().dispose();
+ public boolean run(VerbRunner cb) {
+ Scene s = actor == null ? w.getCurrentScene() : actor.getScene(w);
+ BaseActor a = actor == null || actor.getActorId() == null ? null : s.getActor(actor.getActorId(), true);
+
+ s.setPlayer((CharacterActor) a);
+
+ if (inventory != null && !inventory.equals(w.getCurrentInventory())) {
+ Inventory old = w.getInventory();
+
w.setInventory(inventory);
w.getInventory().loadAssets();
EngineAssetManager.getInstance().finishLoading();
w.getInventory().retrieveAssets();
+
+ old.dispose();
+
}
return false;
diff --git a/blade-engine/src/com/bladecoder/engine/actions/SetStateAction.java b/blade-engine/src/com/bladecoder/engine/actions/SetStateAction.java
index 6edaafb3c..9e5c84710 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/SetStateAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/SetStateAction.java
@@ -15,6 +15,7 @@
******************************************************************************/
package com.bladecoder.engine.actions;
+import com.bladecoder.engine.actions.Param.Type;
import com.bladecoder.engine.model.InteractiveActor;
import com.bladecoder.engine.model.Scene;
import com.bladecoder.engine.model.VerbRunner;
@@ -23,7 +24,7 @@
@ActionDescription(name = "ActorState", value = "Sets the actor state")
public class SetStateAction implements Action {
- @ActionProperty(required = true)
+ @ActionProperty(type = Type.SCENE_INTERACTIVE_ACTOR, required = true)
@ActionPropertyDescription("The target actor")
private SceneActorRef actor;
@@ -43,12 +44,6 @@ public boolean run(VerbRunner cb) {
final Scene s = actor.getScene(w);
String actorId = actor.getActorId();
- if (actorId == null) {
- // if called in a scene verb and no actor is specified, set the state of the
- // scene
- s.setState(state);
- return false;
- }
InteractiveActor a = (InteractiveActor) s.getActor(actorId, true);
diff --git a/blade-engine/src/com/bladecoder/engine/actions/SoundAction.java b/blade-engine/src/com/bladecoder/engine/actions/SoundAction.java
index 9a25b3ee0..a460a064c 100644
--- a/blade-engine/src/com/bladecoder/engine/actions/SoundAction.java
+++ b/blade-engine/src/com/bladecoder/engine/actions/SoundAction.java
@@ -29,9 +29,9 @@ public class SoundAction implements Action {
@ActionPropertyDescription("The actor 'soundId' to play. If empty the current sound will be stopped.")
@ActionProperty(type = Type.STRING)
private String play;
-
+
private World w;
-
+
@Override
public void init(World w) {
this.w = w;
@@ -39,15 +39,17 @@ public void init(World w) {
@Override
public boolean run(VerbRunner cb) {
-
- if(play!= null) {
+
+ if ("$PLAYER".equals(actor))
+ actor = w.getCurrentScene().getPlayer().getId();
+
+ if (play != null) {
w.getCurrentScene().getSoundManager().playSound(actor + "_" + play);
} else {
w.getCurrentScene().getSoundManager().stopCurrentSound(actor);
}
-
+
return false;
}
-
}
diff --git a/blade-engine/src/com/bladecoder/engine/anim/SpriteAlphaTween.java b/blade-engine/src/com/bladecoder/engine/anim/SpriteAlphaTween.java
index 80ed28d85..6d3145d5e 100644
--- a/blade-engine/src/com/bladecoder/engine/anim/SpriteAlphaTween.java
+++ b/blade-engine/src/com/bladecoder/engine/anim/SpriteAlphaTween.java
@@ -26,23 +26,28 @@
* Tween for SpriteActor alpha animation
*/
public class SpriteAlphaTween extends Tween {
-
+
private float startAlpha;
private float targetAlpha;
-
+
public SpriteAlphaTween() {
}
- public void start(SpriteActor target, Type repeatType, int count, float tAlpha, float duration, InterpolationMode interpolation, ActionCallback cb) {
-
+ public void start(SpriteActor target, Type repeatType, int count, float tAlpha, float duration,
+ InterpolationMode interpolation, ActionCallback cb) {
+
setTarget(target);
-
- if(target.getTint() == null)
+
+ if (target.getTint() == null) {
target.setTint(Color.WHITE.cpy());
-
+ } else {
+ // to set the flag dirty
+ target.setTint(target.getTint());
+ }
+
startAlpha = target.getTint().a;
targetAlpha = tAlpha;
-
+
setDuration(duration);
setType(repeatType);
setCount(count);
@@ -51,7 +56,7 @@ public void start(SpriteActor target, Type repeatType, int count, float tAlpha,
if (cb != null) {
setCb(cb);
}
-
+
restart();
}
@@ -59,7 +64,7 @@ public void start(SpriteActor target, Type repeatType, int count, float tAlpha,
public void updateTarget() {
target.getTint().a = startAlpha + getPercent() * (targetAlpha - startAlpha);
}
-
+
@Override
public void write(Json json) {
super.write(json);
@@ -70,8 +75,8 @@ public void write(Json json) {
@Override
public void read(Json json, JsonValue jsonData) {
- super.read(json, jsonData);
-
+ super.read(json, jsonData);
+
startAlpha = json.readValue("startAlpha", float.class, 1.0f, jsonData);
targetAlpha = json.readValue("targetAlpha", float.class, 1.0f, jsonData);
}
diff --git a/blade-engine/src/com/bladecoder/engine/anim/SpriteTintTween.java b/blade-engine/src/com/bladecoder/engine/anim/SpriteTintTween.java
index 3bb28ed4c..13253e422 100644
--- a/blade-engine/src/com/bladecoder/engine/anim/SpriteTintTween.java
+++ b/blade-engine/src/com/bladecoder/engine/anim/SpriteTintTween.java
@@ -26,23 +26,28 @@
* Tween for SpriteActor tint animation
*/
public class SpriteTintTween extends Tween {
-
+
private Color startColor;
private Color targetColor;
-
+
public SpriteTintTween() {
}
- public void start(SpriteActor target, Type repeatType, int count, Color tColor, float duration, InterpolationMode interpolation, ActionCallback cb) {
-
+ public void start(SpriteActor target, Type repeatType, int count, Color tColor, float duration,
+ InterpolationMode interpolation, ActionCallback cb) {
+
setTarget(target);
-
- if(target.getTint() == null)
+
+ if (target.getTint() == null) {
target.setTint(Color.WHITE.cpy());
-
+ } else {
+ // to set the flag dirty
+ target.setTint(target.getTint());
+ }
+
startColor = target.getTint().cpy();
targetColor = tColor.cpy();
-
+
setDuration(duration);
setType(repeatType);
setCount(count);
@@ -51,19 +56,19 @@ public void start(SpriteActor target, Type repeatType, int count, Color tColor,
if (cb != null) {
setCb(cb);
}
-
+
restart();
}
@Override
public void updateTarget() {
-
+
target.getTint().a = startColor.a + getPercent() * (targetColor.a - startColor.a);
target.getTint().r = startColor.r + getPercent() * (targetColor.r - startColor.r);
target.getTint().g = startColor.g + getPercent() * (targetColor.g - startColor.g);
target.getTint().b = startColor.b + getPercent() * (targetColor.b - startColor.b);
}
-
+
@Override
public void write(Json json) {
super.write(json);
@@ -74,8 +79,8 @@ public void write(Json json) {
@Override
public void read(Json json, JsonValue jsonData) {
- super.read(json, jsonData);
-
+ super.read(json, jsonData);
+
startColor = json.readValue("startColor", Color.class, Color.WHITE, jsonData);
targetColor = json.readValue("targetColor", Color.class, Color.WHITE, jsonData);
}
diff --git a/blade-engine/src/com/bladecoder/engine/anim/Timers.java b/blade-engine/src/com/bladecoder/engine/anim/Timers.java
index b173019ab..e9ac23027 100644
--- a/blade-engine/src/com/bladecoder/engine/anim/Timers.java
+++ b/blade-engine/src/com/bladecoder/engine/anim/Timers.java
@@ -23,6 +23,8 @@
import com.badlogic.gdx.utils.Json.Serializable;
import com.badlogic.gdx.utils.JsonValue;
import com.bladecoder.engine.actions.ActionCallback;
+import com.bladecoder.engine.model.Scene;
+import com.bladecoder.engine.model.World;
import com.bladecoder.engine.serialization.ActionCallbackSerializer;
import com.bladecoder.engine.serialization.BladeJson;
@@ -42,19 +44,19 @@ public void addTimer(float time, ActionCallback cb) {
public void clear() {
timers.clear();
}
-
+
public boolean isEmpty() {
return timers.isEmpty();
}
-
+
public void removeTimerWithCb(ActionCallback cb) {
final Iterator it = timers.iterator();
-
+
while (it.hasNext()) {
final Timer t = it.next();
- if(t.cb == cb) {
+ if (t.cb == cb) {
it.remove();
-
+
return;
}
}
@@ -95,18 +97,22 @@ private static class Timer implements Serializable {
public void write(Json json) {
json.writeValue("time", time);
json.writeValue("currentTime", currentTime);
-
- if(cb != null)
- json.writeValue("cb", ActionCallbackSerializer.find(((BladeJson) json).getWorld(), cb));
+
+ if (cb != null) {
+ World w = ((BladeJson) json).getWorld();
+ Scene s = ((BladeJson) json).getScene();
+ json.writeValue("cb", ActionCallbackSerializer.find(w, s, cb));
+ }
}
@Override
public void read(Json json, JsonValue jsonData) {
time = json.readValue("time", Float.class, jsonData);
currentTime = json.readValue("currentTime", Float.class, jsonData);
-
+
BladeJson bjson = (BladeJson) json;
- cb = ActionCallbackSerializer.find(bjson.getWorld(), json.readValue("cb", String.class, jsonData));
+ cb = ActionCallbackSerializer.find(bjson.getWorld(), bjson.getScene(),
+ json.readValue("cb", String.class, jsonData));
}
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/anim/Tween.java b/blade-engine/src/com/bladecoder/engine/anim/Tween.java
index 2ef83303a..8b1d4fb5b 100644
--- a/blade-engine/src/com/bladecoder/engine/anim/Tween.java
+++ b/blade-engine/src/com/bladecoder/engine/anim/Tween.java
@@ -19,6 +19,8 @@
import com.badlogic.gdx.utils.Json.Serializable;
import com.badlogic.gdx.utils.JsonValue;
import com.bladecoder.engine.actions.ActionCallback;
+import com.bladecoder.engine.model.Scene;
+import com.bladecoder.engine.model.World;
import com.bladecoder.engine.serialization.ActionCallbackSerializer;
import com.bladecoder.engine.serialization.BladeJson;
import com.bladecoder.engine.util.InterpolationMode;
@@ -37,7 +39,7 @@ public enum Type {
private int count;
private ActionCallback cb;
-
+
protected T target;
public Tween() {
@@ -65,15 +67,14 @@ public void update(float delta) {
reverse = !reverse;
}
}
-
+
updateTarget();
if (complete) {
callCb();
}
}
-
-
+
/**
* Called to update the target property.
*/
@@ -86,12 +87,11 @@ private void callCb() {
tmpcb.resume();
}
}
-
-
+
public void setTarget(T t) {
target = t;
}
-
+
public T getTarget() {
return target;
}
@@ -147,7 +147,7 @@ public float getDuration() {
public void setDuration(float duration) {
this.duration = duration;
}
-
+
public void setInterpolation(InterpolationMode i) {
interpolation = i;
}
@@ -199,16 +199,19 @@ public void write(Json json) {
json.writeValue("count", count);
json.writeValue("interpolation", interpolation);
-
- if(cb != null)
- json.writeValue("cb", ActionCallbackSerializer.find(((BladeJson) json).getWorld(), cb));
+
+ if (cb != null) {
+ World w = ((BladeJson) json).getWorld();
+ Scene s = ((BladeJson) json).getScene();
+ json.writeValue("cb", ActionCallbackSerializer.find(w, s, cb));
+ }
}
@Override
public void read(Json json, JsonValue jsonData) {
duration = json.readValue("duration", Float.class, jsonData);
time = json.readValue("time", Float.class, jsonData);
-
+
reverse = json.readValue("reverse", Boolean.class, jsonData);
began = json.readValue("began", Boolean.class, jsonData);
complete = json.readValue("complete", Boolean.class, jsonData);
@@ -218,6 +221,7 @@ public void read(Json json, JsonValue jsonData) {
interpolation = json.readValue("interpolation", InterpolationMode.class, jsonData);
BladeJson bjson = (BladeJson) json;
- cb = ActionCallbackSerializer.find(bjson.getWorld(), json.readValue("cb", String.class, jsonData));
+ cb = ActionCallbackSerializer.find(bjson.getWorld(), bjson.getScene(),
+ json.readValue("cb", String.class, jsonData));
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/anim/WalkTween.java b/blade-engine/src/com/bladecoder/engine/anim/WalkTween.java
index 6c534c9b5..8ebbb0e7d 100644
--- a/blade-engine/src/com/bladecoder/engine/anim/WalkTween.java
+++ b/blade-engine/src/com/bladecoder/engine/anim/WalkTween.java
@@ -23,9 +23,13 @@
import com.badlogic.gdx.utils.JsonValue;
import com.bladecoder.engine.actions.ActionCallback;
import com.bladecoder.engine.assets.EngineAssetManager;
+import com.bladecoder.engine.model.AnimationRenderer;
import com.bladecoder.engine.model.CharacterActor;
+import com.bladecoder.engine.model.Scene;
+import com.bladecoder.engine.model.World;
import com.bladecoder.engine.serialization.ActionCallbackSerializer;
import com.bladecoder.engine.serialization.BladeJson;
+import com.bladecoder.engine.util.EngineLogger;
import com.bladecoder.engine.util.InterpolationMode;
/**
@@ -60,34 +64,42 @@ private void walkToNextStep(CharacterActor target) {
Vector2 p0 = walkingPath.get(currentStep);
Vector2 pf = walkingPath.get(currentStep + 1);
- target.startWalkAnim(p0, pf);
-
float s0 = 1.0f;
float sf = 1.0f;
-
+
if (target.getFakeDepth()) {
s0 = target.getScene().getFakeDepthScale(p0.y);
sf = target.getScene().getFakeDepthScale(pf.y);
}
- // float segmentDuration = p0.dst(pf)
- // / (EngineAssetManager.getInstance().getScale() * speed);
+ float sdiff = Math.abs(s0 - sf);
+ if (sdiff > .05f) {
+ // cut the path in two parts if the difference in scale is big
+ Vector2 pi = new Vector2((pf.x + p0.x) / 2, (pf.y + p0.y) / 2);
- // t = dst/((vf+v0)/2)
- float segmentDuration = p0.dst(pf) / (EngineAssetManager.getInstance().getScale() * speed * (s0 + sf) / 2);
+ if (EngineLogger.debugMode()) {
+ String debugText = String.format(
+ "WalkTween insert point: sdiff=%.2f, p0=(%.0f,%.0f), pf=(%.0f,%.0f), pi=(%.0f,%.0f)", sdiff,
+ p0.x, p0.y, pf.x, pf.y, pi.x, pi.y);
- segmentDuration *= (s0 > sf ? s0 / sf : sf / s0);
+ EngineLogger.debug(debugText);
+ }
- InterpolationMode i = InterpolationMode.LINEAR;
+ walkingPath.add(currentStep + 1, pi);
- if (Math.abs(s0 - sf) > .25)
- i = s0 > sf ? InterpolationMode.POW2OUT : InterpolationMode.POW2IN;
+ walkToNextStep(target);
+ return;
+ }
- if (currentStep == walkingPath.size() - 2 && walkCb != null) {
- start(target, Type.NO_REPEAT, 1, pf.x, pf.y, segmentDuration, InterpolationMode.LINEAR, i, walkCb);
- } else {
- start(target, Type.NO_REPEAT, 1, pf.x, pf.y, segmentDuration, InterpolationMode.LINEAR, i, null);
+ if (currentStep == 0 || ((AnimationRenderer) target.getRenderer()).changeDir(p0, pf)) {
+ target.startWalkAnim(p0, pf);
}
+
+ // t = dst/((vf+v0)/2)
+ float segmentDuration = p0.dst(pf) / (EngineAssetManager.getInstance().getScale() * speed * (s0 + sf) / 2);
+
+ start(target, Type.NO_REPEAT, 1, pf.x, pf.y, segmentDuration, InterpolationMode.LINEAR,
+ InterpolationMode.LINEAR, currentStep == walkingPath.size() - 2 ? walkCb : null);
}
private void segmentEnded(CharacterActor target) {
@@ -132,8 +144,11 @@ public void write(Json json) {
json.writeValue("currentStep", currentStep);
json.writeValue("speed", speed);
- if(walkCb != null)
- json.writeValue("walkCb", ActionCallbackSerializer.find(((BladeJson) json).getWorld(), walkCb));
+ if (walkCb != null) {
+ World w = ((BladeJson) json).getWorld();
+ Scene s = ((BladeJson) json).getScene();
+ json.writeValue("walkCb", ActionCallbackSerializer.find(w, s, walkCb));
+ }
}
@SuppressWarnings("unchecked")
@@ -145,7 +160,8 @@ public void read(Json json, JsonValue jsonData) {
currentStep = json.readValue("currentStep", Integer.class, jsonData);
speed = json.readValue("speed", Float.class, jsonData);
- walkCb = ActionCallbackSerializer.find(((BladeJson) json).getWorld(),
- json.readValue("walkCb", String.class, jsonData));
+ World w = ((BladeJson) json).getWorld();
+ Scene s = ((BladeJson) json).getScene();
+ walkCb = ActionCallbackSerializer.find(w, s, json.readValue("walkCb", String.class, jsonData));
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/assets/EngineAssetManager.java b/blade-engine/src/com/bladecoder/engine/assets/EngineAssetManager.java
index 289489be7..a33b1c4cd 100644
--- a/blade-engine/src/com/bladecoder/engine/assets/EngineAssetManager.java
+++ b/blade-engine/src/com/bladecoder/engine/assets/EngineAssetManager.java
@@ -15,6 +15,7 @@
******************************************************************************/
package com.bladecoder.engine.assets;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
@@ -56,8 +57,7 @@ public class EngineAssetManager extends AssetManager {
public static final String WORLD_FILENAME = "world";
- public static final String DESKTOP_PREFS_DIR = "BladeEngine";
- public static final String NOT_DESKTOP_PREFS_DIR = "data/";
+ public static final String DEFAULT_USER_FOLDER = "BladeEngine/";
public static final String ATLASES_DIR = "atlases/";
public static final String MODEL_DIR = "model/";
@@ -87,6 +87,8 @@ public class EngineAssetManager extends AssetManager {
private EngineResolutionFileResolver resResolver;
+ private String userFolder = DEFAULT_USER_FOLDER;
+
protected EngineAssetManager() {
this(new InternalFileHandleResolver());
// getLogger().setLevel(Application.LOG_DEBUG);
@@ -131,14 +133,17 @@ public static EngineAssetManager getInstance() {
return instance;
}
+ public void setUserFolder(String f) {
+ userFolder = f;
+ }
+
/**
* Creates a EngineAssetManager instance for edition. That is:
*
- * - Puts a PathResolver to locate the assets through an absolute path -
- * Puts assets scale to "1"
+ * - Puts a PathResolver to locate the assets through an absolute path - Puts
+ * assets scale to "1"
*
- * @param base
- * is the project base folder
+ * @param base is the project base folder
*/
public static void createEditInstance(String base) {
if (instance != null)
@@ -152,14 +157,16 @@ public static void createEditInstance(String base) {
/**
* All assets will be searched in the selected folder.
*
- * @param base
- * The asset base folder
+ * @param base The asset base folder
*/
public static void setAssetFolder(String base) {
if (instance != null)
instance.dispose();
- instance = new EngineAssetManager(new InternalFolderResolver(base));
+ if (base != null)
+ instance = new EngineAssetManager(new InternalFolderResolver(base));
+ else
+ instance = new EngineAssetManager(new InternalFileHandleResolver());
}
public void forceResolution(String suffix) {
@@ -194,8 +201,7 @@ public FileHandle getModelFile(String filename) {
}
/**
- * Returns a file in the asset directory SEARCHING in the resolution
- * directories
+ * Returns a file in the asset directory SEARCHING in the resolution directories
*/
public FileHandle getResAsset(String filename) {
return resResolver.resolve(filename);
@@ -256,6 +262,7 @@ public Texture getTexture(String filename) {
return get(filename, Texture.class);
}
+ @Override
public void dispose() {
super.dispose();
instance = null;
@@ -277,13 +284,17 @@ public String checkIOSSoundName(String filename) {
return filename;
}
- public void loadMusic(String filename) {
+ public void loadMusic(String filename) throws FileNotFoundException {
String n = checkIOSSoundName(MUSIC_DIR + filename);
if (n == null)
return;
+ if (!FileUtils.exists(EngineAssetManager.getInstance().getAsset(n))) {
+ throw new FileNotFoundException(n);
+ }
+
load(n, Music.class);
}
@@ -306,12 +317,16 @@ public Music getMusic(String filename) {
return get(n, Music.class);
}
- public void loadSound(String filename) {
+ public void loadSound(String filename) throws FileNotFoundException {
String n = checkIOSSoundName(SOUND_DIR + filename);
if (n == null)
return;
+ if (!FileUtils.exists(EngineAssetManager.getInstance().getAsset(n))) {
+ throw new FileNotFoundException(n);
+ }
+
load(n, Sound.class);
}
@@ -356,20 +371,20 @@ public boolean assetExists(String filename) {
}
private Resolution[] getResolutions(FileHandleResolver resolver, int worldWidth, int worldHeight) {
- ArrayList rl = new ArrayList();
+ ArrayList rl = new ArrayList<>();
String list[] = null;
-
- String configRes = Config.getProperty(Config.RESOLUTIONS, null);
-
- if(configRes != null) {
+
+ String configRes = Config.getInstance().getProperty(Config.RESOLUTIONS, null);
+
+ if (configRes != null) {
list = configRes.split(",");
} else {
list = listAssetFiles("ui");
}
-
+
for (String name : list) {
-
+
try {
float scale = Float.parseFloat(name);
@@ -384,6 +399,7 @@ private Resolution[] getResolutions(FileHandleResolver resolver, int worldWidth,
}
Collections.sort(rl, new Comparator() {
+ @Override
public int compare(Resolution a, Resolution b) {
return a.portraitWidth - b.portraitWidth;
}
@@ -443,8 +459,8 @@ public String[] listAssetFiles(String base) {
private String[] getFilesFromJar(String base) {
URL dirURL = EngineAssetManager.class.getResource(base);
- Set result = new HashSet(); // avoid duplicates in case
- // it is a subdirectory
+ Set result = new HashSet<>(); // avoid duplicates in case
+ // it is a subdirectory
if (dirURL.getProtocol().equals("jar")) {
/* A JAR path */
@@ -488,50 +504,27 @@ private String[] getFilesFromJar(String base) {
}
public FileHandle getUserFile(String filename) {
- FileHandle file = null;
-
- if (Gdx.app.getType() == ApplicationType.Desktop || Gdx.app.getType() == ApplicationType.Applet) {
- String dir = Config.getProperty(Config.TITLE_PROP, DESKTOP_PREFS_DIR);
- dir.replace(" ", "");
-
- StringBuilder sb = new StringBuilder();
- sb.append(".").append(dir).append("/").append(filename);
-
- if (System.getProperty("os.name").toLowerCase().contains("mac")
- && System.getenv("HOME").contains("Containers")) {
-
- file = Gdx.files.absolute(System.getenv("HOME") + "/" + sb.toString());
- } else {
-
- file = Gdx.files.external(sb.toString());
- }
- } else {
- file = Gdx.files.local(NOT_DESKTOP_PREFS_DIR + filename);
- }
-
- return file;
+ return getUserFolder().child(filename);
}
public FileHandle getUserFolder() {
FileHandle file = null;
- if (Gdx.app.getType() == ApplicationType.Desktop || Gdx.app.getType() == ApplicationType.Applet) {
- String dir = Config.getProperty(Config.TITLE_PROP, DESKTOP_PREFS_DIR);
- dir.replace(" ", "");
+ if (Gdx.app.getType() == ApplicationType.Desktop) {
+
+ StringBuilder sb = new StringBuilder();
- StringBuilder sb = new StringBuilder(".");
-
if (System.getProperty("os.name").toLowerCase().contains("mac")
&& System.getenv("HOME").contains("Containers")) {
- file = Gdx.files.absolute(System.getenv("HOME") + "/" + sb.append(dir).toString());
+ file = Gdx.files.absolute(System.getenv("HOME") + "/" + sb.append(userFolder).toString());
} else {
- file = Gdx.files.external(sb.append(dir).toString());
+ file = Gdx.files.external(sb.append(userFolder).toString());
}
-
+
} else {
- file = Gdx.files.local(NOT_DESKTOP_PREFS_DIR);
+ file = Gdx.files.local(userFolder);
}
return file;
diff --git a/blade-engine/src/com/bladecoder/engine/i18n/I18N.java b/blade-engine/src/com/bladecoder/engine/i18n/I18N.java
index df10bb112..b7757facf 100644
--- a/blade-engine/src/com/bladecoder/engine/i18n/I18N.java
+++ b/blade-engine/src/com/bladecoder/engine/i18n/I18N.java
@@ -25,47 +25,47 @@ public class I18N {
public static final String ENCODING = "UTF-8";
// public static final String ENCODING = "ISO-8859-1";
- private static ResourceBundle i18nWorld;
- private static ResourceBundle i18nChapter;
- private static Locale locale = Locale.getDefault();
-
- private static String i18nChapterFilename = null;
- private static String i18nWorldFilename = null;
-
- public static void loadChapter(String i18nChapterFilename) {
+ private ResourceBundle i18nWorld;
+ private ResourceBundle i18nChapter;
+ private Locale locale = Locale.getDefault();
+
+ private String i18nChapterFilename = null;
+ private String i18nWorldFilename = null;
+
+ public void loadChapter(String i18nChapterFilename) {
try {
i18nChapter = getBundle(i18nChapterFilename, false);
- I18N.i18nChapterFilename = i18nChapterFilename;
+ this.i18nChapterFilename = i18nChapterFilename;
} catch (Exception e) {
EngineLogger.error("ERROR LOADING BUNDLE: " + i18nChapterFilename);
}
}
- public static void loadWorld(String i18nWorldFilename) {
+ public void loadWorld(String i18nWorldFilename) {
try {
i18nWorld = getBundle(i18nWorldFilename, true);
- I18N.i18nWorldFilename = i18nWorldFilename;
+ this.i18nWorldFilename = i18nWorldFilename;
} catch (Exception e) {
EngineLogger.error("ERROR LOADING BUNDLE: " + i18nWorldFilename);
}
}
-
- public static ResourceBundle getBundle(String filename, boolean clearCache) {
+
+ public ResourceBundle getBundle(String filename, boolean clearCache) {
ResourceBundle rb = null;
-
+
try {
- if(clearCache)
+ if (clearCache)
ResourceBundle.clearCache();
-
+
rb = ResourceBundle.getBundle(filename, locale, new I18NControl(ENCODING));
} catch (Exception e) {
EngineLogger.error("ERROR LOADING BUNDLE: " + filename);
}
-
+
return rb;
}
- public static void setLocale(Locale l) {
+ public void setLocale(Locale l) {
locale = l;
// RELOAD TRANSLATIONS
@@ -78,7 +78,7 @@ public static void setLocale(Locale l) {
}
}
- public static String getString(String key) {
+ public String getString(String key) {
try {
return i18nChapter.getString(key);
} catch (Exception e) {
@@ -89,9 +89,9 @@ public static String getString(String key) {
return key;
}
}
- }
-
- public static Locale getCurrentLocale() {
+ }
+
+ public Locale getCurrentLocale() {
return locale;
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/ink/ExternalFunctions.java b/blade-engine/src/com/bladecoder/engine/ink/ExternalFunctions.java
index 8e30fbcbf..c923f949e 100644
--- a/blade-engine/src/com/bladecoder/engine/ink/ExternalFunctions.java
+++ b/blade-engine/src/com/bladecoder/engine/ink/ExternalFunctions.java
@@ -1,29 +1,147 @@
package com.bladecoder.engine.ink;
+import com.bladecoder.engine.actions.SceneActorRef;
+import com.bladecoder.engine.model.InteractiveActor;
+import com.bladecoder.engine.model.Inventory;
+import com.bladecoder.engine.model.Scene;
import com.bladecoder.engine.model.World;
-import com.bladecoder.ink.runtime.Story.ExternalFunction;
+import com.bladecoder.engine.util.EngineLogger;
+import com.bladecoder.ink.runtime.Story;
+import com.bladecoder.ink.runtime.Story.ExternalFunction0;
+import com.bladecoder.ink.runtime.Story.ExternalFunction1;
+import com.bladecoder.ink.runtime.Story.ExternalFunction2;
public class ExternalFunctions {
- private InkManager inkManager;
+ public static void bindExternalFunctions(final World w, Story story) throws Exception {
- public ExternalFunctions() {
- }
+ story.bindExternalFunction("inInventory", new ExternalFunction1() {
+
+ @Override
+ public Boolean call(String actor) throws Exception {
+ if (actor.charAt(0) == '>')
+ actor = actor.substring(1);
+
+ return w.getInventory().get(actor) != null;
+ }
+ });
+
+ story.bindExternalFunction("getActorState", new ExternalFunction1() {
+
+ @Override
+ public String call(String act) throws Exception {
+ if (act.charAt(0) == '>')
+ act = act.substring(1);
+
+ SceneActorRef actor = new SceneActorRef(act);
+ final Scene s = actor.getScene(w);
+
+ String actorId = actor.getActorId();
+
+ InteractiveActor a = (InteractiveActor) s.getActor(actorId, true);
- public void bindExternalFunctions(final World w, InkManager ink) throws Exception {
+ if (a == null) {
+ EngineLogger.error("getActorState - Actor not found: " + actorId);
+ return "";
+ }
- this.inkManager = ink;
+ return a.getState() == null ? "" : a.getState();
+ }
+ });
- inkManager.getStory().bindExternalFunction("inInventory", new ExternalFunction() {
+ story.bindExternalFunction("getSceneState", new ExternalFunction1() {
@Override
- public Object call(Object[] args) throws Exception {
- String actor = args[0].toString();
+ public String call(String scene) throws Exception {
+ if (scene.charAt(0) == '>')
+ scene = scene.substring(1);
+
+ final Scene s = w.getScene(scene);
+
+ if (s == null) {
+ EngineLogger.error("getSceneState - Scene not found: " + scene);
+ return "";
+ }
+
+ return s.getState() == null ? "" : s.getState();
+ }
+ });
+
+ story.bindExternalFunction("getPlayer", new ExternalFunction0() {
+ @Override
+ public String call() throws Exception {
+ return w.getCurrentScene().getPlayer().getId();
+ }
+ });
+
+ story.bindExternalFunction("inInventory2", new ExternalFunction2() {
+
+ @Override
+ public Boolean call(String actor, String inventory) throws Exception {
if (actor.charAt(0) == '>')
actor = actor.substring(1);
- return w.getInventory().get(actor) != null;
+ Inventory inv = w.getInventories().get(inventory);
+
+ if (inv == null) {
+ EngineLogger.debug("InkExternalFunction::inInventory2: Inventory not found: " + inventory);
+
+ return false;
+ }
+
+ return inv.get(actor) != null;
+ }
+ });
+
+ story.bindExternalFunction("getCurrentScene", new ExternalFunction0() {
+
+ @Override
+ public String call() throws Exception {
+ return w.getCurrentScene().getId();
+ }
+ });
+
+ story.bindExternalFunction("isDebug", new ExternalFunction0() {
+
+ @Override
+ public Boolean call() throws Exception {
+ return EngineLogger.debugMode();
+ }
+ });
+
+ story.bindExternalFunction("getProperty", new ExternalFunction1() {
+
+ @Override
+ public String call(String p) throws Exception {
+ if (p.charAt(0) == '>')
+ p = p.substring(1);
+
+ String v = w.getCustomProperty(p);
+ return v == null ? "" : v;
+ }
+ });
+
+ story.bindExternalFunction("isVisible", new ExternalFunction1() {
+
+ @Override
+ public Boolean call(String act) throws Exception {
+ if (act.charAt(0) == '>')
+ act = act.substring(1);
+
+ SceneActorRef actor = new SceneActorRef(act);
+ final Scene s = actor.getScene(w);
+
+ String actorId = actor.getActorId();
+
+ InteractiveActor a = (InteractiveActor) s.getActor(actorId, true);
+
+ if (a == null) {
+ EngineLogger.error("getActorState - Actor not found: " + actorId);
+ return false;
+ }
+
+ return a.isVisible();
}
});
}
diff --git a/blade-engine/src/com/bladecoder/engine/ink/InkManager.java b/blade-engine/src/com/bladecoder/engine/ink/InkManager.java
index f08996b17..5212ad315 100644
--- a/blade-engine/src/com/bladecoder/engine/ink/InkManager.java
+++ b/blade-engine/src/com/bladecoder/engine/ink/InkManager.java
@@ -33,7 +33,8 @@
import com.bladecoder.ink.runtime.ListDefinition;
import com.bladecoder.ink.runtime.Story;
-public class InkManager implements VerbRunner, Serializable {
+public class InkManager implements Serializable {
+ public final static int KEY_SIZE = 10;
public final static char NAME_VALUE_TAG_SEPARATOR = ':';
public final static char NAME_VALUE_PARAM_SEPARATOR = '=';
private final static String PARAM_SEPARATOR = ",";
@@ -42,7 +43,6 @@ public class InkManager implements VerbRunner, Serializable {
private ResourceBundle i18n;
private Story story = null;
- private ExternalFunctions externalFunctions;
private ActionCallback cb;
@@ -50,22 +50,18 @@ public class InkManager implements VerbRunner, Serializable {
// the verbCallbacks may not exist. So, we search the Cb lazily when needed.
private String sCb;
- private ArrayList actions;
-
private boolean wasInCutmode;
private String storyName;
- private int ip = -1;
-
private final World w;
+ private InkVerbRunner inkVerbRunner = new InkVerbRunner();
+
private Thread loaderThread;
public InkManager(World w) {
this.w = w;
- externalFunctions = new ExternalFunctions();
- actions = new ArrayList<>();
}
public void newStory(final String name) throws Exception {
@@ -82,7 +78,7 @@ private void loadStory(String name) {
String json = getJsonString(asset.read());
story = new Story(json);
- externalFunctions.bindExternalFunctions(w, this);
+ ExternalFunctions.bindExternalFunctions(w, story);
storyName = name;
@@ -110,7 +106,7 @@ private void loadStoryState(String stateString) {
public void loadI18NBundle() {
if (getStoryName() != null
&& EngineAssetManager.getInstance().getModelFile(storyName + "-ink.properties").exists())
- i18n = I18N.getBundle(EngineAssetManager.MODEL_DIR + storyName + "-ink", true);
+ i18n = w.getI18N().getBundle(EngineAssetManager.MODEL_DIR + storyName + "-ink", true);
}
public String translateLine(String line) {
@@ -124,7 +120,13 @@ public String translateLine(String line) {
for (String k : keys) {
try {
- translated += i18n.getString(k);
+ // some untranslated words may follow the key
+ String k2 = k.substring(0, KEY_SIZE);
+ translated += i18n.getString(k2);
+ if (k.length() > KEY_SIZE) {
+ String trailing = k.substring(KEY_SIZE);
+ translated += trailing;
+ }
} catch (Exception e) {
EngineLogger.error("MISSING TRANSLATION KEY: " + key);
return key;
@@ -150,7 +152,7 @@ public boolean compareVariable(String name, String value) {
if (story.getVariablesState().get(name) instanceof InkList) {
return ((InkList) story.getVariablesState().get(name)).ContainsItemNamed(value);
} else {
- return story.getVariablesState().get(name).toString().equals(value);
+ return story.getVariablesState().get(name).toString().equals(value == null ? "" : value);
}
}
@@ -183,7 +185,11 @@ private void continueMaximally() {
waitIfNotLoaded();
String line = null;
- actions.clear();
+
+ // We create a new InkVerbRunner every ink loop to avoid pending cb.resume() to
+ // execute in the new actions
+ inkVerbRunner.cancel();
+ inkVerbRunner = new InkVerbRunner();
HashMap currentLineParams = new HashMap<>();
@@ -221,8 +227,8 @@ private void continueMaximally() {
}
- if (actions.size() > 0) {
- run(null, null);
+ if (inkVerbRunner.getActions().size() > 0) {
+ inkVerbRunner.run(null, null);
} else {
if (hasChoices()) {
@@ -231,11 +237,12 @@ private void continueMaximally() {
w.getListener().dialogOptions();
} else if (cb != null || sCb != null) {
if (cb == null) {
- cb = ActionCallbackSerializer.find(w, sCb);
+ cb = ActionCallbackSerializer.find(w, w.getCurrentScene(), sCb);
}
ActionCallback tmpcb = cb;
cb = null;
+ sCb = null;
tmpcb.resume();
}
}
@@ -282,31 +289,34 @@ private void processCommand(HashMap params, String line) {
processParams(Arrays.asList(commandParams), params);
}
- if ("leave".equals(commandName)) {
+ if ("LeaveNow".equals(commandName)) {
boolean init = true;
+ String initVerb = null;
if (params.get("init") != null)
init = Boolean.parseBoolean(params.get("init"));
- w.setCurrentScene(params.get("scene"), init);
- } else {
-
- // for backward compatibility
- if ("action".equals(commandName)) {
- commandName = commandParams[0].trim();
- params.remove(commandName);
- }
+ if (params.get("initVerb") != null)
+ initVerb = params.get("initVerb");
+ w.setCurrentScene(params.get("scene"), init, initVerb);
+ } else {
// Some preliminar validation to see if it's an action
- if (commandName.length() > 0 && Character.isUpperCase(commandName.charAt(0))) {
+ if (commandName.length() > 0) {
// Try to create action by default
Action action;
try {
- action = ActionFactory.createByClass("com.bladecoder.engine.actions." + commandName + "Action",
- params);
+
+ Class> c = ActionFactory.getClassTags().get(commandName);
+
+ if (c == null && commandName.indexOf('.') == -1) {
+ commandName = "com.bladecoder.engine.actions." + commandName + "Action";
+ }
+
+ action = ActionFactory.create(commandName, params);
action.init(w);
- actions.add(action);
+ inkVerbRunner.getActions().add(action);
} catch (ClassNotFoundException | ReflectionException e) {
EngineLogger.error(e.getMessage(), e);
}
@@ -331,8 +341,6 @@ private void processTextLine(HashMap params, String line) {
}
if (!params.containsKey("actor") && w.getCurrentScene().getPlayer() != null) {
- // params.put("actor", Scene.VAR_PLAYER);
-
if (!params.containsKey("type")) {
params.put("type", Type.SUBTITLE.toString());
}
@@ -348,44 +356,21 @@ private void processTextLine(HashMap params, String line) {
Action action = null;
if (!params.containsKey("actor")) {
- action = ActionFactory.createByClass("com.bladecoder.engine.actions.TextAction", params);
+ action = ActionFactory.create("Text", params);
} else {
- action = ActionFactory.createByClass("com.bladecoder.engine.actions.SayAction", params);
+ action = ActionFactory.create("Say", params);
}
action.init(w);
- actions.add(action);
+ inkVerbRunner.getActions().add(action);
} catch (ClassNotFoundException | ReflectionException e) {
EngineLogger.error(e.getMessage(), e);
}
}
- private void nextStep() {
- if (ip < 0) {
- continueMaximally();
- } else {
- boolean stop = false;
-
- while (ip < actions.size() && !stop) {
- Action a = actions.get(ip);
-
- try {
- if (a.run(this))
- stop = true;
- else
- ip++;
- } catch (Exception e) {
- EngineLogger.error("EXCEPTION EXECUTING ACTION: " + a.getClass().getSimpleName(), e);
- ip++;
- }
- }
-
- if (ip >= actions.size() && !stop)
- continueMaximally();
- }
- }
-
public Story getStory() {
+ waitIfNotLoaded();
+
return story;
}
@@ -398,6 +383,7 @@ public void runPath(String path, ActionCallback cb) throws Exception {
}
this.cb = cb;
+ sCb = null;
story.choosePathString(path);
continueMaximally();
@@ -406,7 +392,7 @@ public void runPath(String path, ActionCallback cb) throws Exception {
public boolean hasChoices() {
waitIfNotLoaded();
- return (story != null && actions.size() == 0 && story.getCurrentChoices().size() > 0);
+ return (story != null && inkVerbRunner.getActions().size() == 0 && story.getCurrentChoices().size() > 0);
}
public List getChoices() {
@@ -456,12 +442,6 @@ private String getJsonString(InputStream is) throws IOException {
}
}
- @Override
- public void resume() {
- ip++;
- nextStep();
- }
-
public void selectChoice(int i) {
w.setCutMode(wasInCutmode);
@@ -473,44 +453,6 @@ public void selectChoice(int i) {
}
}
- @Override
- public ArrayList getActions() {
- return actions;
- }
-
- @Override
- public void run(String currentTarget, ActionCallback cb) {
- ip = 0;
- nextStep();
- }
-
- @Override
- public int getIP() {
- return ip;
- }
-
- @Override
- public void setIP(int ip) {
- this.ip = ip;
- }
-
- @Override
- public void cancel() {
- ArrayList actions = getActions();
-
- for (Action c : actions) {
- if (c instanceof VerbRunner)
- ((VerbRunner) c).cancel();
- }
-
- ip = actions.size();
- }
-
- @Override
- public String getCurrentTarget() {
- return null;
- }
-
public String getStoryName() {
return storyName;
}
@@ -545,6 +487,10 @@ public void run() {
loaderThread.start();
}
+ public InkVerbRunner getVerbRunner() {
+ return inkVerbRunner;
+ }
+
@Override
public void write(Json json) {
BladeJson bjson = (BladeJson) json;
@@ -556,22 +502,22 @@ public void write(Json json) {
json.writeValue("wasInCutmode", wasInCutmode);
if (cb == null && sCb != null)
- cb = ActionCallbackSerializer.find(w, sCb);
+ cb = ActionCallbackSerializer.find(w, w.getCurrentScene(), sCb);
if (cb != null)
- json.writeValue("cb", ActionCallbackSerializer.find(w, cb));
+ json.writeValue("cb", ActionCallbackSerializer.find(w, w.getCurrentScene(), cb));
// SAVE ACTIONS
json.writeArrayStart("actions");
- for (Action a : actions) {
+ for (Action a : inkVerbRunner.getActions()) {
ActionUtils.writeJson(a, json);
}
json.writeArrayEnd();
- json.writeValue("ip", ip);
+ json.writeValue("ip", inkVerbRunner.getIP());
json.writeArrayStart("actionsSer");
- for (Action a : actions) {
+ for (Action a : inkVerbRunner.getActions()) {
if (a instanceof Serializable) {
json.writeObjectStart();
((Serializable) a).write(json);
@@ -613,22 +559,24 @@ public void read(Json json, JsonValue jsonData) {
sCb = json.readValue("cb", String.class, jsonData);
// READ ACTIONS
- actions.clear();
JsonValue actionsValue = jsonData.get("actions");
+
+ inkVerbRunner = new InkVerbRunner();
+
for (int i = 0; i < actionsValue.size; i++) {
JsonValue aValue = actionsValue.get(i);
Action a = ActionUtils.readJson(w, json, aValue);
- actions.add(a);
+ inkVerbRunner.getActions().add(a);
}
- ip = json.readValue("ip", Integer.class, jsonData);
+ inkVerbRunner.setIP(json.readValue("ip", Integer.class, jsonData));
actionsValue = jsonData.get("actionsSer");
int i = 0;
- for (Action a : actions) {
+ for (Action a : inkVerbRunner.getActions()) {
if (a instanceof Serializable && i < actionsValue.size) {
if (actionsValue.get(i) == null)
break;
@@ -645,4 +593,84 @@ public void read(Json json, JsonValue jsonData) {
}
}
}
+
+ public final class InkVerbRunner implements VerbRunner {
+
+ private ArrayList actions;
+ private int ip = -1;
+ private boolean cancelled = false;
+
+ public InkVerbRunner() {
+ actions = new ArrayList<>();
+ }
+
+ @Override
+ public void resume() {
+ ip++;
+
+ nextStep();
+ }
+
+ @Override
+ public ArrayList getActions() {
+ return actions;
+ }
+
+ @Override
+ public void run(String currentTarget, ActionCallback cb) {
+ ip = 0;
+ nextStep();
+ }
+
+ @Override
+ public int getIP() {
+ return ip;
+ }
+
+ @Override
+ public void setIP(int ip) {
+ this.ip = ip;
+ }
+
+ @Override
+ public void cancel() {
+ cancelled = true;
+ ip = actions.size();
+ }
+
+ @Override
+ public String getCurrentTarget() {
+ return null;
+ }
+
+ private void nextStep() {
+ if (cancelled)
+ return;
+
+ if (ip < 0) {
+ continueMaximally();
+ } else {
+ boolean stop = false;
+
+ while (ip < actions.size() && !stop && !cancelled) {
+ Action a = actions.get(ip);
+
+ try {
+ if (a.run(this))
+ stop = true;
+ else
+ ip++;
+ } catch (Exception e) {
+ EngineLogger.error("EXCEPTION EXECUTING ACTION: InkManager - " + ip + " - "
+ + a.getClass().getSimpleName() + " - " + e.getMessage(), e);
+ ip++;
+ }
+ }
+
+ if (ip >= actions.size() && !stop)
+ continueMaximally();
+ }
+ }
+
+ }
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/ActorRenderer.java b/blade-engine/src/com/bladecoder/engine/model/ActorRenderer.java
index 2f3ad0e30..d1f51c307 100644
--- a/blade-engine/src/com/bladecoder/engine/model/ActorRenderer.java
+++ b/blade-engine/src/com/bladecoder/engine/model/ActorRenderer.java
@@ -24,19 +24,24 @@
public interface ActorRenderer extends Serializable, AssetConsumer {
public void update(float delta);
+
public void draw(SpriteBatch batch, float x, float y, float scaleX, float scaleY, float rotation, Color tint);
-
+
public float getWidth();
+
public float getHeight();
-
+
public int getOrgAlign();
+
public void setOrgAlign(int align);
-
+
/**
* Compute the bbox based in the size of the animation/sprite. T
*
- * @param bbox The polygon to update. It will be updated when an animation starts/finishs.
+ * @param bbox The polygon to update. It will be updated when an animation
+ * starts/finishes.
*/
public void updateBboxFromRenderer(Polygon bbox);
-}
+ public void setWorld(World world);
+}
diff --git a/blade-engine/src/com/bladecoder/engine/model/AnimationRenderer.java b/blade-engine/src/com/bladecoder/engine/model/AnimationRenderer.java
index f79688fe2..931c001c4 100644
--- a/blade-engine/src/com/bladecoder/engine/model/AnimationRenderer.java
+++ b/blade-engine/src/com/bladecoder/engine/model/AnimationRenderer.java
@@ -16,6 +16,8 @@
package com.bladecoder.engine.model;
import java.util.HashMap;
+import java.util.SortedMap;
+import java.util.TreeMap;
import com.badlogic.gdx.math.Polygon;
import com.badlogic.gdx.math.Vector2;
@@ -41,7 +43,7 @@ public abstract class AnimationRenderer implements ActorRenderer {
private final static float DEFAULT_DIM = 200;
- protected HashMap fanims = new HashMap();
+ protected HashMap fanims = new HashMap<>();
/** Starts this anim the first time that the scene is loaded */
protected String initAnimation;
@@ -51,9 +53,11 @@ public abstract class AnimationRenderer implements ActorRenderer {
protected CacheEntry currentSource;
protected boolean flipX;
- protected final HashMap sourceCache = new HashMap();
+ protected final HashMap sourceCache = new HashMap<>();
protected Polygon bbox;
+ protected World world;
+
public class CacheEntry {
public int refCounter;
}
@@ -120,6 +124,29 @@ public String getCurrentAnimationId() {
}
+ /**
+ * Checks if the character faces the target point to avoid changing the
+ * animation.
+ */
+ public boolean changeDir(Vector2 p0, Vector2 pf) {
+ int idx = getCurrentAnimationId().indexOf('.');
+
+ if (idx == -1) {
+ return true;
+ }
+
+ String id = getCurrentAnimationId().substring(0, idx);
+
+ String directionString = getDirectionString(p0, pf, getDirs(id, fanims));
+
+ if (getCurrentAnimationId().substring(idx + 1).equals(directionString)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder(super.toString());
@@ -137,6 +164,7 @@ public String toString() {
return sb.toString();
}
+ @Override
public void updateBboxFromRenderer(Polygon bbox) {
this.bbox = bbox;
computeBbox();
@@ -350,8 +378,7 @@ protected String getDirectionString(Vector2 p0, Vector2 pf, int numDirs) {
* FRONT, BACK) 2 -> when 2 dir animation mode (RIGHT, LEFT) 0 -> when no dirs
* availables for the base animation -1 -> when base animation doesn't exists
*
- * @param base
- * Base animation
+ * @param base Base animation
* @param fanims
* @return -1, 0, 2, 4 or 8
*/
@@ -379,7 +406,10 @@ public void write(Json json) {
BladeJson bjson = (BladeJson) json;
if (bjson.getMode() == Mode.MODEL) {
- json.writeValue("fanims", fanims, HashMap.class, null);
+ SortedMap sortedAnims = new TreeMap<>();
+ sortedAnims.putAll(fanims);
+
+ json.writeValue("fanims", sortedAnims, sortedAnims.getClass(), null);
json.writeValue("initAnimation", initAnimation);
json.writeValue("orgAlign", orgAlign);
@@ -417,4 +447,9 @@ public void read(Json json, JsonValue jsonData) {
flipX = json.readValue("flipX", Boolean.class, jsonData);
}
}
+
+ @Override
+ public void setWorld(World world) {
+ this.world = world;
+ }
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/AtlasRenderer.java b/blade-engine/src/com/bladecoder/engine/model/AtlasRenderer.java
index 8d53f31bf..6d01e11bd 100644
--- a/blade-engine/src/com/bladecoder/engine/model/AtlasRenderer.java
+++ b/blade-engine/src/com/bladecoder/engine/model/AtlasRenderer.java
@@ -55,7 +55,7 @@ public String[] getInternalAnimations(AnimationDesc anim) {
TextureAtlas atlas = EngineAssetManager.getInstance().getTextureAtlas(anim.source);
Array animations = atlas.getRegions();
- ArrayList l = new ArrayList();
+ ArrayList l = new ArrayList<>();
for (int i = 0; i < animations.size; i++) {
AtlasRegion a = animations.get(i);
@@ -70,7 +70,7 @@ public String[] getInternalAnimations(AnimationDesc anim) {
public void update(float delta) {
if (faTween != null) {
faTween.update(delta);
- if (faTween.isComplete()) {
+ if (faTween != null && faTween.isComplete()) {
faTween = null;
computeBbox();
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/BaseActor.java b/blade-engine/src/com/bladecoder/engine/model/BaseActor.java
index d083e7bfe..ce4d692f9 100644
--- a/blade-engine/src/com/bladecoder/engine/model/BaseActor.java
+++ b/blade-engine/src/com/bladecoder/engine/model/BaseActor.java
@@ -32,9 +32,10 @@
abstract public class BaseActor implements Serializable {
protected String id;
protected Scene scene = null;
- protected boolean visible = true;
- protected final Polygon bbox = new Polygon();
+ private boolean visible = true;
+ private final Polygon bbox = new Polygon();
private String initScene;
+ protected long dirtyProps = 0L;
public String getId() {
return id;
@@ -58,6 +59,7 @@ public boolean isVisible() {
public void setVisible(boolean visible) {
this.visible = visible;
+ setDirtyProp(DirtyProps.VISIBLE);
}
public void setScene(Scene s) {
@@ -70,6 +72,14 @@ public Scene getScene() {
abstract public void update(float delta);
+ protected void setDirtyProp(DirtyProps dp) {
+ dirtyProps |= (1L << dp.ordinal());
+ }
+
+ protected boolean isDirty(DirtyProps dp) {
+ return (dirtyProps & (1L << dp.ordinal())) != 0;
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@@ -92,7 +102,10 @@ public float getY() {
}
public void setPosition(float x, float y) {
- bbox.setPosition(x, y);
+ if (x != bbox.getX() || y != bbox.getY()) {
+ bbox.setPosition(x, y);
+ setDirtyProp(DirtyProps.POS);
+ }
}
public String getInitScene() {
@@ -110,14 +123,18 @@ public void write(Json json) {
json.writeValue("id", id);
json.writeValue("bbox", bbox.getVertices());
} else {
-
+ if (dirtyProps != 0L)
+ json.writeValue("dirtyProps", dirtyProps);
}
- float worldScale = EngineAssetManager.getInstance().getScale();
- Vector2 scaledPos = new Vector2(bbox.getX() / worldScale, bbox.getY() / worldScale);
- json.writeValue("pos", scaledPos);
+ if (bjson.getMode() == Mode.MODEL || isDirty(DirtyProps.POS)) {
+ float worldScale = EngineAssetManager.getInstance().getScale();
+ Vector2 scaledPos = new Vector2(bbox.getX() / worldScale, bbox.getY() / worldScale);
+ json.writeValue("pos", scaledPos);
+ }
- json.writeValue("visible", visible);
+ if (bjson.getMode() == Mode.MODEL || isDirty(DirtyProps.VISIBLE))
+ json.writeValue("visible", visible);
}
@Override
@@ -130,8 +147,6 @@ public void read(Json json, JsonValue jsonData) {
if (verts.length > 0)
bbox.setVertices(verts);
- } else {
-
}
Vector2 pos = json.readValue("pos", Vector2.class, jsonData);
@@ -140,8 +155,10 @@ public void read(Json json, JsonValue jsonData) {
float worldScale = EngineAssetManager.getInstance().getScale();
bbox.setPosition(pos.x * worldScale, pos.y * worldScale);
bbox.setScale(worldScale, worldScale);
-
- visible = json.readValue("visible", boolean.class, visible, jsonData);
}
+
+ visible = json.readValue("visible", boolean.class, visible, jsonData);
+
+ dirtyProps = json.readValue("dirtyProps", long.class, 0L, jsonData);
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/CharacterActor.java b/blade-engine/src/com/bladecoder/engine/model/CharacterActor.java
index 07d869e27..93864f85c 100644
--- a/blade-engine/src/com/bladecoder/engine/model/CharacterActor.java
+++ b/blade-engine/src/com/bladecoder/engine/model/CharacterActor.java
@@ -57,6 +57,8 @@ public Color getTextColor() {
public void setTextColor(Color textColor) {
this.textColor = textColor;
+
+ setDirtyProp(DirtyProps.TEXT_COLOR);
}
public String getTextStyle() {
@@ -65,6 +67,7 @@ public String getTextStyle() {
public void setTextStyle(String textStyle) {
this.textStyle = textStyle;
+ setDirtyProp(DirtyProps.TEXT_STYLE);
}
public String getStandAnim() {
@@ -104,6 +107,8 @@ public void addDialog(Dialog d) {
public void setWalkingSpeed(float s) {
walkingSpeed = s;
+
+ setDirtyProp(DirtyProps.WALKING_SPEED);
}
public float getWalkingSpeed() {
@@ -116,6 +121,7 @@ public Vector2 getTalkingTextPos() {
public void setTalkingTextPos(Vector2 talkingTextPos) {
this.talkingTextPos = talkingTextPos;
+ setDirtyProp(DirtyProps.TALKING_TEXT_POS);
}
public void lookat(Vector2 p) {
@@ -125,7 +131,7 @@ public void lookat(Vector2 p) {
inAnim();
removeTween(SpritePosTween.class);
((AnimationRenderer) renderer).startAnimation(standAnim, Tween.Type.SPRITE_DEFINED, -1, null,
- new Vector2(bbox.getX(), bbox.getY()), p);
+ new Vector2(getBBox().getX(), getBBox().getY()), p);
outAnim(Tween.Type.SPRITE_DEFINED);
}
@@ -171,15 +177,13 @@ public void startWalkAnim(Vector2 p0, Vector2 pf) {
/**
* Walking Support
*
- * @param pf
- * Final position to walk
- * @param cb
- * The action callback
+ * @param pf Final position to walk
+ * @param cb The action callback
*/
public void goTo(Vector2 pf, ActionCallback cb, boolean ignoreWalkZone) {
EngineLogger.debug(MessageFormat.format("GOTO {0},{1}", pf.x, pf.y));
- Vector2 p0 = new Vector2(bbox.getX(), bbox.getY());
+ Vector2 p0 = new Vector2(getBBox().getX(), getBBox().getY());
// stop previous movement
if (tweens.size() > 0) {
@@ -270,22 +274,40 @@ public void write(Json json) {
if (bjson.getMode() == Mode.MODEL) {
if (textStyle != null)
json.writeValue("textStyle", textStyle);
+
+ if (textColor != null)
+ json.writeValue("textColor", textColor);
+
+ if (talkingTextPos != null) {
+ float worldScale = EngineAssetManager.getInstance().getScale();
+ json.writeValue("talkingTextPos",
+ new Vector2(talkingTextPos.x / worldScale, talkingTextPos.y / worldScale));
+ }
} else {
- json.writeValue("standAnim", standAnim);
- json.writeValue("walkAnim", walkAnim);
- json.writeValue("talkAnim", talkAnim);
- }
+ if (!DEFAULT_STAND_ANIM.equals(standAnim))
+ json.writeValue("standAnim", standAnim);
- json.writeValue("walkingSpeed", walkingSpeed);
+ if (!DEFAULT_WALK_ANIM.equals(walkAnim))
+ json.writeValue("walkAnim", walkAnim);
- if (textColor != null)
- json.writeValue("textColor", textColor);
+ if (!DEFAULT_TALK_ANIM.equals(talkAnim))
+ json.writeValue("talkAnim", talkAnim);
- if (talkingTextPos != null) {
- float worldScale = EngineAssetManager.getInstance().getScale();
- json.writeValue("talkingTextPos",
- new Vector2(talkingTextPos.x / worldScale, talkingTextPos.y / worldScale));
+ if (isDirty(DirtyProps.TEXT_STYLE))
+ json.writeValue("textStyle", textStyle);
+
+ if (isDirty(DirtyProps.TEXT_COLOR))
+ json.writeValue("textColor", textColor);
+
+ if (isDirty(DirtyProps.TALKING_TEXT_POS)) {
+ float worldScale = EngineAssetManager.getInstance().getScale();
+ json.writeValue("talkingTextPos",
+ new Vector2(talkingTextPos.x / worldScale, talkingTextPos.y / worldScale));
+ }
}
+
+ if (bjson.getMode() == Mode.MODEL || isDirty(DirtyProps.WALKING_SPEED))
+ json.writeValue("walkingSpeed", walkingSpeed);
}
@SuppressWarnings("unchecked")
@@ -302,8 +324,6 @@ public void read(Json json, JsonValue jsonData) {
d.setActor(this);
}
- textStyle = json.readValue("textStyle", String.class, jsonData);
-
} else {
if (dialogs != null) {
JsonValue dialogsValue = jsonData.get("dialogs");
@@ -317,14 +337,15 @@ public void read(Json json, JsonValue jsonData) {
}
}
- standAnim = json.readValue("standAnim", String.class, jsonData);
- walkAnim = json.readValue("walkAnim", String.class, jsonData);
- talkAnim = json.readValue("talkAnim", String.class, jsonData);
+ standAnim = json.readValue("standAnim", String.class, DEFAULT_STAND_ANIM, jsonData);
+ walkAnim = json.readValue("walkAnim", String.class, DEFAULT_WALK_ANIM, jsonData);
+ talkAnim = json.readValue("talkAnim", String.class, DEFAULT_TALK_ANIM, jsonData);
}
+ textStyle = json.readValue("textStyle", String.class, textStyle, jsonData);
walkingSpeed = json.readValue("walkingSpeed", float.class, walkingSpeed, jsonData);
- textColor = json.readValue("textColor", Color.class, jsonData);
- talkingTextPos = json.readValue("talkingTextPos", Vector2.class, jsonData);
+ textColor = json.readValue("textColor", Color.class, textColor, jsonData);
+ talkingTextPos = json.readValue("talkingTextPos", Vector2.class, talkingTextPos, jsonData);
if (talkingTextPos != null) {
float worldScale = EngineAssetManager.getInstance().getScale();
diff --git a/blade-engine/src/com/bladecoder/engine/model/Dialog.java b/blade-engine/src/com/bladecoder/engine/model/Dialog.java
index 7aa9b6b51..d180a4a78 100644
--- a/blade-engine/src/com/bladecoder/engine/model/Dialog.java
+++ b/blade-engine/src/com/bladecoder/engine/model/Dialog.java
@@ -28,7 +28,7 @@ public class Dialog implements Serializable {
public final static String DEFAULT_DIALOG_VERB = "dialog";
- private ArrayList options = new ArrayList();
+ private ArrayList options = new ArrayList<>();
private int currentOption = -1;
@@ -60,7 +60,7 @@ public Dialog selectOption(int i) {
*/
public List getChoices() {
ArrayList options = getVisibleOptions();
- List choices = new ArrayList(options.size());
+ List choices = new ArrayList<>(options.size());
for (DialogOption o : options) {
choices.add(o.getText());
@@ -106,7 +106,7 @@ public ArrayList getOptions() {
}
private ArrayList getVisibleOptions() {
- ArrayList visible = new ArrayList();
+ ArrayList visible = new ArrayList<>();
for (DialogOption o : options) {
if (o.isVisible())
@@ -172,6 +172,8 @@ public void read(Json json, JsonValue jsonData) {
o.read(json, jsonValue);
i++;
}
+
+ currentOption = json.readValue("currentOption", int.class, jsonData);
}
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/DirtyProps.java b/blade-engine/src/com/bladecoder/engine/model/DirtyProps.java
new file mode 100644
index 000000000..616e76133
--- /dev/null
+++ b/blade-engine/src/com/bladecoder/engine/model/DirtyProps.java
@@ -0,0 +1,6 @@
+package com.bladecoder.engine.model;
+
+public enum DirtyProps {
+ POS, VISIBLE, DESC, ZINDEX, INTERACTION, STATE, LAYER, ROT, SCALEX, SCALEY, TINT, FAKE_DEPTH, BBOX_FROM_RENDERER,
+ WALKING_SPEED, TEXT_COLOR, TALKING_TEXT_POS, TEXT_STYLE;
+}
diff --git a/blade-engine/src/com/bladecoder/engine/model/ImageRenderer.java b/blade-engine/src/com/bladecoder/engine/model/ImageRenderer.java
index c6dc0635a..640b5ff3d 100644
--- a/blade-engine/src/com/bladecoder/engine/model/ImageRenderer.java
+++ b/blade-engine/src/com/bladecoder/engine/model/ImageRenderer.java
@@ -19,6 +19,7 @@
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Json;
@@ -119,7 +120,7 @@ public void startAnimation(String id, Tween.Type repeatType, int count, ActionCa
disposeSource(currentAnimation.source);
currentAnimation = fa;
- currentSource = (ImageCacheEntry) sourceCache.get(fa.source);
+ currentSource = sourceCache.get(fa.source);
// If the source is not loaded. Load it.
if (currentSource == null || currentSource.refCounter < 1) {
@@ -128,7 +129,7 @@ public void startAnimation(String id, Tween.Type repeatType, int count, ActionCa
retrieveSource(fa.source);
- currentSource = (ImageCacheEntry) sourceCache.get(fa.source);
+ currentSource = sourceCache.get(fa.source);
if (currentSource == null) {
EngineLogger.error("Could not load AnimationDesc: " + id);
@@ -210,11 +211,13 @@ private void retrieveSource(String source) {
((ImageCacheEntry) entry).tex = EngineAssetManager.getInstance()
.getTexture(EngineAssetManager.IMAGE_DIR + source);
+
+ ((ImageCacheEntry) entry).tex.setFilter(TextureFilter.Linear, TextureFilter.Linear);
}
}
private String getI18NSource(String source) {
- String lang = I18N.getCurrentLocale().getLanguage();
+ String lang = world.getI18N().getCurrentLocale().getLanguage();
int pointIdx = source.lastIndexOf('.');
String ext = source.substring(pointIdx);
diff --git a/blade-engine/src/com/bladecoder/engine/model/InteractiveActor.java b/blade-engine/src/com/bladecoder/engine/model/InteractiveActor.java
index 51d807def..dae7999c7 100644
--- a/blade-engine/src/com/bladecoder/engine/model/InteractiveActor.java
+++ b/blade-engine/src/com/bladecoder/engine/model/InteractiveActor.java
@@ -56,6 +56,8 @@ public class InteractiveActor extends BaseActor implements Comparable= 0
&& currentMusicDelay > desc.getRepeatDelay() + desc.getInitialDelay()) {
- currentMusicDelay = desc.getInitialDelay();
+ currentMusicDelay = desc.getInitialDelay() + delta;
playMusic();
}
}
@@ -206,7 +211,13 @@ public void dispose() {
public void loadAssets() {
if (music == null && desc != null) {
EngineLogger.debug("LOADING MUSIC: " + desc.getFilename());
- EngineAssetManager.getInstance().loadMusic(desc.getFilename());
+
+ try {
+ EngineAssetManager.getInstance().loadMusic(desc.getFilename());
+ } catch (FileNotFoundException e) {
+ EngineLogger.error("Not found: " + e.getLocalizedMessage());
+ desc = null;
+ }
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/ObstacleActor.java b/blade-engine/src/com/bladecoder/engine/model/ObstacleActor.java
index ea2b8fbe3..3a4f40e03 100644
--- a/blade-engine/src/com/bladecoder/engine/model/ObstacleActor.java
+++ b/blade-engine/src/com/bladecoder/engine/model/ObstacleActor.java
@@ -27,14 +27,15 @@
*/
public class ObstacleActor extends BaseActor {
+ @Override
public void setVisible(boolean visible) {
- this.visible = visible;
+ super.setVisible(visible);
if (scene != null && scene.getPolygonalNavGraph() != null) {
if (visible)
- scene.getPolygonalNavGraph().addDinamicObstacle(bbox);
+ scene.getPolygonalNavGraph().addDinamicObstacle(getBBox());
else
- scene.getPolygonalNavGraph().removeDinamicObstacle(bbox);
+ scene.getPolygonalNavGraph().removeDinamicObstacle(getBBox());
}
}
@@ -42,17 +43,18 @@ public void setVisible(boolean visible) {
public void update(float delta) {
}
+ @Override
public void setPosition(float x, float y) {
boolean inNavGraph = false;
if (scene != null && scene.getPolygonalNavGraph() != null) {
- inNavGraph = scene.getPolygonalNavGraph().removeDinamicObstacle(bbox);
+ inNavGraph = scene.getPolygonalNavGraph().removeDinamicObstacle(getBBox());
}
- bbox.setPosition(x, y);
+ getBBox().setPosition(x, y);
if (inNavGraph) {
- scene.getPolygonalNavGraph().addDinamicObstacle(bbox);
+ scene.getPolygonalNavGraph().addDinamicObstacle(getBBox());
}
}
@@ -60,8 +62,8 @@ public void setPosition(float x, float y) {
public void write(Json json) {
BladeJson bjson = (BladeJson) json;
if (bjson.getMode() == Mode.MODEL) {
- PolygonUtils.ensureClockWise(bbox.getVertices(), 0, bbox.getVertices().length);
- bbox.dirty();
+ PolygonUtils.ensureClockWise(getBBox().getVertices(), 0, getBBox().getVertices().length);
+ getBBox().dirty();
}
super.write(json);
diff --git a/blade-engine/src/com/bladecoder/engine/model/ParticleRenderer.java b/blade-engine/src/com/bladecoder/engine/model/ParticleRenderer.java
index 23ca5d999..e38835225 100644
--- a/blade-engine/src/com/bladecoder/engine/model/ParticleRenderer.java
+++ b/blade-engine/src/com/bladecoder/engine/model/ParticleRenderer.java
@@ -222,4 +222,10 @@ public void read(Json json, JsonValue jsonData) {
lastAnimationTime = json.readValue("lastAnimationTime", Float.class, jsonData);
}
}
+
+ @Override
+ public void setWorld(World world) {
+ // TODO Auto-generated method stub
+
+ }
}
\ No newline at end of file
diff --git a/blade-engine/src/com/bladecoder/engine/model/Scene.java b/blade-engine/src/com/bladecoder/engine/model/Scene.java
index b189462fa..eed8eca6d 100644
--- a/blade-engine/src/com/bladecoder/engine/model/Scene.java
+++ b/blade-engine/src/com/bladecoder/engine/model/Scene.java
@@ -18,6 +18,8 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import com.badlogic.gdx.graphics.Color;
@@ -186,10 +188,6 @@ public void init() {
timers.clear();
textManager.reset();
-
- // Run INIT action
- if (getVerb("init") != null)
- runVerb("init");
}
public VerbManager getVerbManager() {
@@ -642,15 +640,15 @@ public void retrieveAssets() {
camera.setScrollingDimensions(sceneSize.x * scale, sceneSize.y * scale);
}
+ soundManager.retrieveAssets();
+ textManager.getVoiceManager().retrieveAssets();
+
// RETRIEVE ACTORS
for (BaseActor a : actors.values()) {
if (a instanceof AssetConsumer)
((AssetConsumer) a).retrieveAssets();
}
- soundManager.retrieveAssets();
- textManager.getVoiceManager().retrieveAssets();
-
if (getWorld().getListener() != null)
getWorld().getListener().text(textManager.getCurrentText());
}
@@ -662,8 +660,6 @@ public void dispose() {
EngineAssetManager.getInstance().disposeAtlas(backgroundAtlas);
}
- // orderedActors.clear();
-
for (BaseActor a : actors.values()) {
if (a instanceof AssetConsumer)
((AssetConsumer) a).dispose();
@@ -694,12 +690,16 @@ public PolygonalNavGraph getPolygonalNavGraph() {
@Override
public void write(Json json) {
BladeJson bjson = (BladeJson) json;
+ bjson.setScene(this);
+
if (bjson.getMode() == Mode.MODEL) {
json.writeValue("id", id);
json.writeValue("layers", layers, layers.getClass(), SceneLayer.class);
- json.writeValue("actors", actors);
+ SortedMap sortedActors = new TreeMap<>();
+ sortedActors.putAll(actors);
+ json.writeValue("actors", sortedActors);
if (backgroundAtlas != null) {
json.writeValue("backgroundAtlas", backgroundAtlas);
@@ -718,7 +718,9 @@ public void write(Json json) {
SceneActorRef actorRef;
json.writeObjectStart("actors");
- for (BaseActor a : actors.values()) {
+ SortedMap sortedActors = new TreeMap<>();
+ sortedActors.putAll(actors);
+ for (BaseActor a : sortedActors.values()) {
actorRef = new SceneActorRef(a.getInitScene(), a.getId());
json.writeValue(actorRef.toString(), a);
}
@@ -747,12 +749,15 @@ public void write(Json json) {
json.writeValue("player", player);
json.writeValue("walkZone", walkZone);
+ bjson.setScene(null);
}
@SuppressWarnings("unchecked")
@Override
public void read(Json json, JsonValue jsonData) {
BladeJson bjson = (BladeJson) json;
+ bjson.setScene(this);
+
if (bjson.getMode() == Mode.MODEL) {
id = json.readValue("id", String.class, jsonData);
@@ -780,6 +785,9 @@ public void read(Json json, JsonValue jsonData) {
depthVector = json.readValue("depthVector", Vector2.class, jsonData);
+ sceneSize = json.readValue("sceneSize", Vector2.class, jsonData);
+
+ // FOR BACKWARDS COMPATIBILITY
if (jsonData.get("polygonalNavGraph") != null) {
JsonValue jsonValuePNG = jsonData.get("polygonalNavGraph");
@@ -792,9 +800,9 @@ public void read(Json json, JsonValue jsonData) {
WalkZoneActor wz = new WalkZoneActor();
wz.setId("walkzone");
- wz.bbox.setVertices(walkZonePol.getVertices());
- wz.bbox.setScale(walkZonePol.getScaleX(), walkZonePol.getScaleY());
- wz.bbox.setPosition(walkZonePol.getX(), walkZonePol.getY());
+ wz.getBBox().setVertices(walkZonePol.getVertices());
+ wz.getBBox().setScale(walkZonePol.getScaleX(), walkZonePol.getScaleY());
+ wz.getBBox().setPosition(walkZonePol.getX(), walkZonePol.getY());
wz.setScene(this);
wz.setInitScene(id);
@@ -802,8 +810,6 @@ public void read(Json json, JsonValue jsonData) {
walkZone = wz.getId();
}
- sceneSize = json.readValue("sceneSize", Vector2.class, jsonData);
-
} else {
JsonValue jsonValueActors = jsonData.get("actors");
SceneActorRef actorRef;
@@ -862,5 +868,7 @@ public void read(Json json, JsonValue jsonData) {
if (jsonData.get("walkZone") != null)
walkZone = json.readValue("walkZone", String.class, jsonData);
+
+ bjson.setScene(null);
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/SceneCamera.java b/blade-engine/src/com/bladecoder/engine/model/SceneCamera.java
index 88a23d017..5b00d60ae 100644
--- a/blade-engine/src/com/bladecoder/engine/model/SceneCamera.java
+++ b/blade-engine/src/com/bladecoder/engine/model/SceneCamera.java
@@ -31,11 +31,11 @@
import com.bladecoder.engine.assets.EngineAssetManager;
import com.bladecoder.engine.util.InterpolationMode;
-public class SceneCamera extends OrthographicCamera implements Serializable {
-
+public class SceneCamera extends OrthographicCamera implements Serializable {
+
private static final float START_SCROLLX = 0.1f;
private static final float START_SCROLLY = 0.15f;
-
+
// to avoid create new vector when calling getPosition
private final static Vector2 tmpPos = new Vector2();
@@ -43,96 +43,93 @@ public class SceneCamera extends OrthographicCamera implements Serializable {
private float startScrollDistanceY;
private float scrollingWidth, scrollingHeight;
-
+
private CameraTween cameraTween;
-
+
private Matrix4 parallaxView = new Matrix4();
private Matrix4 parallaxCombined = new Matrix4();
private Vector3 tmp = new Vector3();
private Vector3 tmp2 = new Vector3();
-
+
public SceneCamera() {
}
-
+
public void create(float worldWidth, float worldHeight) {
scrollingWidth = worldWidth;
scrollingHeight = worldHeight;
-
+
zoom = 1.0f;
-
+
setToOrtho(false, worldWidth, worldHeight);
update();
-
- startScrollDistanceX = worldWidth * START_SCROLLX;
+
+ startScrollDistanceX = worldWidth * START_SCROLLX;
startScrollDistanceY = worldHeight * START_SCROLLY;
}
-
- public float getWidth() {
- return viewportWidth;
- }
-
- public float getHeight() {
- return viewportHeight;
- }
-
+
public float getScrollingWidth() {
return scrollingWidth;
}
-
+
public float getScrollingHeight() {
return scrollingHeight;
}
public void setScrollingDimensions(float w, float h) {
scrollingWidth = Math.max(w, viewportWidth);
- scrollingHeight = Math.max(h, viewportHeight);
+ scrollingHeight = Math.max(h, viewportHeight);
}
-
+
public void update(float delta) {
- if(cameraTween != null) {
+ if (cameraTween != null) {
cameraTween.update(delta);
- if(cameraTween.isComplete()) {
+ if (cameraTween != null && cameraTween.isComplete()) {
cameraTween = null;
}
}
- }
+ }
public void setPosition(float x, float y) {
float maxleft = viewportWidth / 2 * zoom;
float maxright = (scrollingWidth - viewportWidth / 2 * zoom);
-
+
float maxbottom = viewportHeight / 2 * zoom;
float maxtop = (scrollingHeight - viewportHeight / 2 * zoom);
- x = MathUtils.clamp(x, maxleft, maxright);
+ x = MathUtils.clamp(x, maxleft, maxright);
y = MathUtils.clamp(y, maxbottom, maxtop);
position.set(x, y, 0);
-
+
update();
}
-
+
public void setZoom(float zoom) {
this.zoom = zoom;
update();
}
-
+
public Vector2 getPosition() {
Vector3 p = position;
return tmpPos.set(p.x, p.y);
}
-
+
public float getZoom() {
return zoom;
}
+ public void stopAnim() {
+ cameraTween = null;
+ }
+
/**
* Create camera animation.
*/
- public void startAnimation(float destX, float destY, float zoom, float duration, InterpolationMode interpolation, ActionCallback cb) {
+ public void startAnimation(float destX, float destY, float zoom, float duration, InterpolationMode interpolation,
+ ActionCallback cb) {
cameraTween = new CameraTween();
-
+
cameraTween.start(this, Tween.Type.NO_REPEAT, 1, destX, destY, zoom, duration, interpolation, cb);
}
@@ -140,8 +137,8 @@ public void getInputUnProject(Viewport viewport, Vector3 out) {
out.set(Gdx.input.getX(), Gdx.input.getY(), 0);
- unproject(out, viewport.getScreenX(), viewport.getScreenY(),
- viewport.getScreenWidth(), viewport.getScreenHeight());
+ unproject(out, viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(),
+ viewport.getScreenHeight());
out.x = MathUtils.clamp(out.x, 0, scrollingWidth - 1);
out.y = MathUtils.clamp(out.y, 0, scrollingHeight - 1);
@@ -152,7 +149,7 @@ public void updatePos(SpriteActor followActor) {
float posx = followActor.getX();
float cy = position.y;
float posy = followActor.getY();
-
+
boolean translate = false;
if (cx - posx > startScrollDistanceX * zoom) {
@@ -162,16 +159,16 @@ public void updatePos(SpriteActor followActor) {
cx = cx + (posx - cx - startScrollDistanceX * zoom);
translate = true;
}
-
- if (cy - posy + followActor.getHeight() > startScrollDistanceY * zoom) {
+
+ if (cy - posy + followActor.getHeight() > startScrollDistanceY * zoom) {
cy = cy - (cy - posy - startScrollDistanceY * zoom);
translate = true;
} else if (posy - cy > startScrollDistanceY * zoom) {
cy = cy + (posy - cy - startScrollDistanceY * zoom);
translate = true;
}
-
- if(translate) {
+
+ if (translate) {
setPosition(cx, cy);
}
}
@@ -179,61 +176,61 @@ public void updatePos(SpriteActor followActor) {
public void scene2screen(Viewport viewport, Vector3 out) {
project(out, 0, 0, viewport.getScreenWidth(), viewport.getScreenHeight());
}
-
- public Matrix4 calculateParallaxMatrix (float parallaxX, float parallaxY) {
+
+ public Matrix4 calculateParallaxMatrix(float parallaxX, float parallaxY) {
update();
tmp.set(position);
// tmp.x *= parallaxX;
tmp.y *= parallaxY;
-
- tmp.x = (tmp.x - scrollingWidth / 2) * parallaxX + scrollingWidth / 2;
+
+ tmp.x = (tmp.x - scrollingWidth / 2) * parallaxX + scrollingWidth / 2;
parallaxView.setToLookAt(tmp, tmp2.set(tmp).add(direction), up);
parallaxCombined.set(projection);
Matrix4.mul(parallaxCombined.val, parallaxView.val);
return parallaxCombined;
}
-
+
@Override
public void write(Json json) {
float worldScale = EngineAssetManager.getInstance().getScale();
-
+
json.writeValue("width", viewportWidth / worldScale);
json.writeValue("height", viewportHeight / worldScale);
json.writeValue("scrollingWidth", scrollingWidth / worldScale);
json.writeValue("scrollingHeight", scrollingHeight / worldScale);
-
+
Vector2 p = getPosition();
- p.x = p.x/worldScale;
- p.y = p.y/worldScale;
+ p.x = p.x / worldScale;
+ p.y = p.y / worldScale;
json.writeValue("pos", p);
json.writeValue("zoom", getZoom());
-
- if(cameraTween != null)
+
+ if (cameraTween != null)
json.writeValue("cameraTween", cameraTween);
}
@Override
public void read(Json json, JsonValue jsonData) {
float worldScale = EngineAssetManager.getInstance().getScale();
-
+
viewportWidth = json.readValue("width", Float.class, jsonData) * worldScale;
viewportHeight = json.readValue("height", Float.class, jsonData) * worldScale;
scrollingWidth = json.readValue("scrollingWidth", Float.class, jsonData) * worldScale;
scrollingHeight = json.readValue("scrollingHeight", Float.class, jsonData) * worldScale;
Vector2 pos = json.readValue("pos", Vector2.class, jsonData);
- pos.x *= worldScale;
- pos.y *= worldScale;
+ pos.x *= worldScale;
+ pos.y *= worldScale;
float z = json.readValue("zoom", Float.class, jsonData);
-
+
create(viewportWidth, viewportHeight);
this.zoom = z;
position.set(pos.x, pos.y, 0);
update();
cameraTween = json.readValue("cameraTween", CameraTween.class, jsonData);
- if(cameraTween != null) {
+ if (cameraTween != null) {
cameraTween.setTarget(this);
}
- }
+ }
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/SceneSoundManager.java b/blade-engine/src/com/bladecoder/engine/model/SceneSoundManager.java
index 6ebf3862b..73dca9f40 100644
--- a/blade-engine/src/com/bladecoder/engine/model/SceneSoundManager.java
+++ b/blade-engine/src/com/bladecoder/engine/model/SceneSoundManager.java
@@ -1,5 +1,6 @@
package com.bladecoder.engine.model;
+import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map.Entry;
@@ -18,12 +19,12 @@
*/
public class SceneSoundManager implements Serializable, AssetConsumer {
- private HashMap loadedSounds = new HashMap(0);
+ private HashMap loadedSounds = new HashMap<>(0);
private final World w;
-
+
// the global configurable by user volume
public static float VOLUME_MULTIPLIER = 1f;
-
+
public SceneSoundManager(World w) {
this.w = w;
}
@@ -45,7 +46,14 @@ public void playSound(String id) {
s = loadedSounds.get(id);
EngineLogger.debug("LOADING SOUND: " + s.desc.getId() + " - " + s.desc.getFilename());
- EngineAssetManager.getInstance().loadSound(s.desc.getFilename());
+
+ try {
+ EngineAssetManager.getInstance().loadSound(s.desc.getFilename());
+ } catch (FileNotFoundException e) {
+ EngineLogger.error("Sound file not found:" + e.getMessage());
+ return;
+ }
+
EngineAssetManager.getInstance().finishLoading();
s.sound = EngineAssetManager.getInstance().getSound(s.desc.getFilename());
}
@@ -114,8 +122,7 @@ public void pause() {
@Override
public void dispose() {
for (LoadedSound s : loadedSounds.values()) {
- // EngineLogger.debug("DISPOSING SOUND: " + s.desc.getId() + " - " +
- // s.desc.getFilename());
+
if (s.playing)
s.sound.stop();
@@ -126,9 +133,14 @@ public void dispose() {
@Override
public void loadAssets() {
for (LoadedSound s : loadedSounds.values()) {
- // EngineLogger.debug("LOADING SOUND: " + s.desc.getId() + " - " +
- // s.desc.getFilename());
- EngineAssetManager.getInstance().loadSound(s.desc.getFilename());
+
+ try {
+ EngineAssetManager.getInstance().loadSound(s.desc.getFilename());
+ } catch (FileNotFoundException e) {
+ loadedSounds.remove(s.desc.getId());
+ EngineLogger.error("Sound file not found:" + e.getMessage());
+ }
+
}
}
@@ -150,16 +162,16 @@ public void retrieveAssets() {
@Override
public void write(Json json) {
- json.writeValue("loadedSounds", loadedSounds, loadedSounds.getClass(), SoundDesc.class);
+ json.writeValue("loadedSounds", loadedSounds, loadedSounds.getClass(), LoadedSound.class);
}
@SuppressWarnings("unchecked")
@Override
public void read(Json json, JsonValue jsonData) {
- loadedSounds = json.readValue("loadedSounds", HashMap.class, SoundDesc.class, jsonData);
+ loadedSounds = json.readValue("loadedSounds", HashMap.class, LoadedSound.class, jsonData);
if (loadedSounds == null)
- loadedSounds = new HashMap(0);
+ loadedSounds = new HashMap<>(0);
// Retrieve desc from World sound description.
for (Entry e : loadedSounds.entrySet()) {
@@ -167,7 +179,7 @@ public void read(Json json, JsonValue jsonData) {
}
}
- static class LoadedSound {
+ public static class LoadedSound {
transient SoundDesc desc;
transient Sound sound;
diff --git a/blade-engine/src/com/bladecoder/engine/model/Sprite3DRenderer.java b/blade-engine/src/com/bladecoder/engine/model/Sprite3DRenderer.java
index adba4bcc8..956e9aff4 100644
--- a/blade-engine/src/com/bladecoder/engine/model/Sprite3DRenderer.java
+++ b/blade-engine/src/com/bladecoder/engine/model/Sprite3DRenderer.java
@@ -738,7 +738,8 @@ public void write(Json json) {
} else {
if (animationCb != null)
- json.writeValue("animationCb", ActionCallbackSerializer.find(bjson.getWorld(), animationCb));
+ json.writeValue("animationCb",
+ ActionCallbackSerializer.find(bjson.getWorld(), bjson.getScene(), animationCb));
json.writeValue("currentCount", currentCount);
json.writeValue("currentAnimationType", currentAnimationType);
@@ -770,7 +771,7 @@ public void read(Json json, JsonValue jsonData) {
renderShadow = json.readValue("renderShadow", Boolean.class, jsonData);
} else {
- animationCb = ActionCallbackSerializer.find(bjson.getWorld(),
+ animationCb = ActionCallbackSerializer.find(bjson.getWorld(), bjson.getScene(),
json.readValue("animationCb", String.class, jsonData));
currentCount = json.readValue("currentCount", Integer.class, jsonData);
diff --git a/blade-engine/src/com/bladecoder/engine/model/SpriteActor.java b/blade-engine/src/com/bladecoder/engine/model/SpriteActor.java
index 8ff8f20c4..121ad6ca4 100644
--- a/blade-engine/src/com/bladecoder/engine/model/SpriteActor.java
+++ b/blade-engine/src/com/bladecoder/engine/model/SpriteActor.java
@@ -64,6 +64,7 @@ public boolean getFakeDepth() {
public void setFakeDepth(boolean fd) {
fakeDepth = fd;
+ setDirtyProp(DirtyProps.FAKE_DEPTH);
}
@Override
@@ -89,9 +90,11 @@ public void setBboxFromRenderer(boolean v) {
this.bboxFromRenderer = v;
if (v)
- renderer.updateBboxFromRenderer(bbox);
+ renderer.updateBboxFromRenderer(getBBox());
else
renderer.updateBboxFromRenderer(null);
+
+ setDirtyProp(DirtyProps.BBOX_FROM_RENDERER);
}
public float getWidth() {
@@ -105,11 +108,11 @@ public float getHeight() {
public float getScale() {
return scaleX;
}
-
+
public float getScaleX() {
return scaleX;
}
-
+
public float getScaleY() {
return scaleY;
}
@@ -120,27 +123,32 @@ public Color getTint() {
public void setTint(Color tint) {
this.tint = tint;
+ setDirtyProp(DirtyProps.TINT);
}
public void setScale(float scale) {
setScale(scale, scale);
}
-
+
public void setScale(float scaleX, float scaleY) {
this.scaleX = scaleX;
this.scaleY = scaleY;
if (bboxFromRenderer)
- bbox.setScale(scaleX, scaleY);
+ getBBox().setScale(scaleX, scaleY);
else {
float worldScale = EngineAssetManager.getInstance().getScale();
- bbox.setScale(scaleX * worldScale, scaleY * worldScale);
+ getBBox().setScale(scaleX * worldScale, scaleY * worldScale);
}
+
+ setDirtyProp(DirtyProps.SCALEX);
+ setDirtyProp(DirtyProps.SCALEY);
}
public void setRot(float rot) {
this.rot = rot;
- bbox.setRotation(rot);
+ getBBox().setRotation(rot);
+ setDirtyProp(DirtyProps.ROT);
}
public float getRot() {
@@ -151,7 +159,7 @@ public float getRot() {
public void update(float delta) {
super.update(delta);
- if (visible) {
+ if (isVisible()) {
renderer.update(delta);
for (int i = 0; i < tweens.size(); i++) {
@@ -271,7 +279,7 @@ protected void outAnim(Type repeatType) {
public void addTween(Tween tween) {
removeTween(tween.getClass());
-
+
tweens.add(tween);
}
@@ -298,7 +306,7 @@ public void retrieveAssets() {
renderer.retrieveAssets();
// Call setPosition to recalc fake depth and camera follow
- setPosition(bbox.getX(), bbox.getY());
+ setPosition(getBBox().getX(), getBBox().getY());
}
@Override
@@ -314,33 +322,46 @@ public void write(Json json) {
// Reset vertices if bboxFromRenderer to save always with 0.0 value
if (bboxFromRenderer && bjson.getMode() == Mode.MODEL) {
- float[] verts = bbox.getVertices();
- bbox.setVertices(new float[8]);
+ float[] verts = getBBox().getVertices();
+ getBBox().setVertices(new float[8]);
super.write(json);
- bbox.setVertices(verts);
+ getBBox().setVertices(verts);
} else {
super.write(json);
}
-
+
if (bjson.getMode() == Mode.MODEL) {
json.writeValue("renderer", renderer, null);
+
+ if (tint != null)
+ json.writeValue("tint", tint);
} else {
json.writeValue("renderer", renderer);
json.writeValue("tweens", tweens, ArrayList.class, Tween.class);
- json.writeValue("playingSound", playingSound);
+
+ if (playingSound != null)
+ json.writeValue("playingSound", playingSound);
+
+ if (isDirty(DirtyProps.TINT))
+ json.writeValue("tint", tint);
}
- json.writeValue("scaleX", scaleX);
- json.writeValue("scaleY", scaleY);
- json.writeValue("rot", rot);
-
- if(tint != null)
- json.writeValue("tint", tint);
-
- json.writeValue("fakeDepth", fakeDepth);
- json.writeValue("bboxFromRenderer", bboxFromRenderer);
+ if (bjson.getMode() == Mode.MODEL || isDirty(DirtyProps.SCALEX))
+ json.writeValue("scaleX", scaleX);
+
+ if (bjson.getMode() == Mode.MODEL || isDirty(DirtyProps.SCALEY))
+ json.writeValue("scaleY", scaleY);
+
+ if (bjson.getMode() == Mode.MODEL || isDirty(DirtyProps.ROT))
+ json.writeValue("rot", rot);
+
+ if (bjson.getMode() == Mode.MODEL || isDirty(DirtyProps.FAKE_DEPTH))
+ json.writeValue("fakeDepth", fakeDepth);
+
+ if (bjson.getMode() == Mode.MODEL || isDirty(DirtyProps.BBOX_FROM_RENDERER))
+ json.writeValue("bboxFromRenderer", bboxFromRenderer);
}
@SuppressWarnings("unchecked")
@@ -354,11 +375,11 @@ public void read(Json json, JsonValue jsonData) {
} else {
tweens = json.readValue("tweens", ArrayList.class, Tween.class, jsonData);
- if(tweens == null) {
+ if (tweens == null) {
EngineLogger.debug("Couldn't load state of actor: " + id);
return;
}
-
+
for (Tween t : tweens)
t.setTarget(this);
@@ -367,6 +388,8 @@ public void read(Json json, JsonValue jsonData) {
playingSound = json.readValue("playingSound", String.class, jsonData);
}
+ renderer.setWorld(bjson.getWorld());
+
if (jsonData.get("scale") != null) {
scaleX = json.readValue("scale", float.class, jsonData);
scaleY = scaleX;
@@ -374,7 +397,7 @@ public void read(Json json, JsonValue jsonData) {
scaleX = json.readValue("scaleX", float.class, scaleX, jsonData);
scaleY = json.readValue("scaleY", float.class, scaleY, jsonData);
}
-
+
rot = json.readValue("rot", float.class, rot, jsonData);
tint = json.readValue("tint", Color.class, tint, jsonData);
@@ -390,10 +413,13 @@ public void read(Json json, JsonValue jsonData) {
bboxFromRenderer = json.readValue("bboxFromRenderer", boolean.class, bboxFromRenderer, jsonData);
if (bboxFromRenderer)
- renderer.updateBboxFromRenderer(bbox);
+ renderer.updateBboxFromRenderer(getBBox());
setScale(scaleX, scaleY);
setRot(rot);
+
+ // restore dirtyProps after rotation and scale
+ dirtyProps = json.readValue("dirtyProps", long.class, 0L, jsonData);
}
}
\ No newline at end of file
diff --git a/blade-engine/src/com/bladecoder/engine/model/Text.java b/blade-engine/src/com/bladecoder/engine/model/Text.java
index 9b610a76d..952e03c0f 100644
--- a/blade-engine/src/com/bladecoder/engine/model/Text.java
+++ b/blade-engine/src/com/bladecoder/engine/model/Text.java
@@ -97,8 +97,11 @@ public void write(Json json) {
json.writeValue("voiceId", voiceId);
json.writeValue("animation", animation);
- if (cb != null)
- json.writeValue("cb", ActionCallbackSerializer.find(((BladeJson) json).getWorld(), cb));
+ if (cb != null) {
+ World w = ((BladeJson) json).getWorld();
+ Scene s = ((BladeJson) json).getScene();
+ json.writeValue("cb", ActionCallbackSerializer.find(w, s, cb));
+ }
}
@Override
@@ -113,6 +116,8 @@ public void read(Json json, JsonValue jsonData) {
actorId = json.readValue("actorId", String.class, jsonData);
voiceId = json.readValue("voiceId", String.class, jsonData);
animation = json.readValue("animation", String.class, jsonData);
- cb = ActionCallbackSerializer.find(((BladeJson) json).getWorld(), json.readValue("cb", String.class, jsonData));
+ BladeJson bjson = (BladeJson) json;
+ cb = ActionCallbackSerializer.find(bjson.getWorld(), bjson.getScene(),
+ json.readValue("cb", String.class, jsonData));
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/TextManager.java b/blade-engine/src/com/bladecoder/engine/model/TextManager.java
index 7510f0a94..023ef898f 100644
--- a/blade-engine/src/com/bladecoder/engine/model/TextManager.java
+++ b/blade-engine/src/com/bladecoder/engine/model/TextManager.java
@@ -46,7 +46,7 @@ public class TextManager implements Serializable {
public static final float RECT_MARGIN = 18f;
public static final float RECT_BORDER = 2f;
- public static final boolean AUTO_HIDE_TEXTS = Config.getProperty(Config.AUTO_HIDE_TEXTS, true);
+ public static final boolean AUTO_HIDE_TEXTS = Config.getInstance().getProperty(Config.AUTO_HIDE_TEXTS, true);
private float inScreenTime;
private Text currentText = null;
@@ -69,7 +69,7 @@ public void addText(String str, float x, float y, boolean queue, Text.Type type,
String actorId, String voiceId, String talkAnimation, ActionCallback cb) {
if (str.charAt(0) == I18N.PREFIX)
- str = I18N.getString(str.substring(1));
+ str = scene.getWorld().getI18N().getString(str.substring(1));
String s = str.replace("\\n", "\n");
@@ -148,7 +148,8 @@ public Text getCurrentText() {
}
private void setCurrentText(Text t) {
- if (currentText != null && currentText.type == Type.TALK && currentText.actorId != null) {
+ if (currentText != null && (currentText.type == Type.TALK || currentText.animation != null)
+ && currentText.actorId != null) {
CharacterActor a = (CharacterActor) scene.getActor(currentText.actorId, false);
// restore previous stand animation
@@ -165,7 +166,7 @@ private void setCurrentText(Text t) {
voiceManager.play(t.voiceId);
// Start talk animation
- if (t.type == Type.TALK && t.actorId != null) {
+ if ((t.type == Type.TALK || t.animation != null) && t.actorId != null) {
CharacterActor a = (CharacterActor) scene.getActor(t.actorId, false);
previousCharacterAnim = ((AnimationRenderer) a.getRenderer()).getCurrentAnimationId();
diff --git a/blade-engine/src/com/bladecoder/engine/model/TextRenderer.java b/blade-engine/src/com/bladecoder/engine/model/TextRenderer.java
index 438e63557..0bf58f50e 100644
--- a/blade-engine/src/com/bladecoder/engine/model/TextRenderer.java
+++ b/blade-engine/src/com/bladecoder/engine/model/TextRenderer.java
@@ -59,6 +59,8 @@ public class TextRenderer implements ActorRenderer {
// with the translation is not ready.
private transient String editorTranslatedText;
+ private World world;
+
public TextRenderer() {
}
@@ -93,7 +95,7 @@ public void draw(SpriteBatch batch, float x, float y, float scaleX, float scaleY
String tt = text;
if (tt.charAt(0) == I18N.PREFIX)
- tt = I18N.getString(tt.substring(1));
+ tt = world.getI18N().getString(tt.substring(1));
if (editorTranslatedText != null)
tt = editorTranslatedText;
@@ -180,13 +182,14 @@ public String getText() {
}
public void setText(String text) {
- this.text = text;
- this.editorTranslatedText = text;
+ setText(text, text);
}
public void setText(String text, String translatedText) {
this.text = text;
this.editorTranslatedText = translatedText;
+
+ updateLayout();
}
public String getFontName() {
@@ -302,7 +305,25 @@ public void loadAssets() {
params.fontParameters.magFilter = TextureFilter.Linear;
params.fontParameters.minFilter = TextureFilter.Linear;
- EngineAssetManager.getInstance().load(fontName + getFontSize() + ".ttf", BitmapFont.class, params);
+ EngineAssetManager.getInstance().load(fontName + getFontSize() + EngineAssetManager.FONT_EXT, BitmapFont.class,
+ params);
+ }
+
+ private void updateLayout() {
+ if (font == null)
+ return;
+
+ String tt = editorTranslatedText;
+
+ if (tt == null)
+ tt = text;
+
+ if (tt.charAt(0) == I18N.PREFIX)
+ tt = world.getI18N().getString(tt.substring(1));
+
+ layout.setText(font, tt, color, 0, textAlign, false);
+
+ computeBbox();
}
@Override
@@ -315,17 +336,7 @@ public void retrieveAssets() {
font = EngineAssetManager.getInstance().get(fontName + getFontSize() + ".ttf", BitmapFont.class);
- String tt = text;
-
- if (tt.charAt(0) == I18N.PREFIX)
- tt = I18N.getString(tt.substring(1));
-
- if (editorTranslatedText != null)
- tt = editorTranslatedText;
-
- layout.setText(font, tt, color, 0, textAlign, false);
-
- computeBbox();
+ updateLayout();
}
@Override
@@ -376,4 +387,9 @@ public void read(Json json, JsonValue jsonData) {
}
}
+
+ @Override
+ public void setWorld(World world) {
+ this.world = world;
+ }
}
\ No newline at end of file
diff --git a/blade-engine/src/com/bladecoder/engine/model/Transition.java b/blade-engine/src/com/bladecoder/engine/model/Transition.java
index 011a03b61..08037bc17 100644
--- a/blade-engine/src/com/bladecoder/engine/model/Transition.java
+++ b/blade-engine/src/com/bladecoder/engine/model/Transition.java
@@ -50,7 +50,7 @@ public void update(float delta) {
// must stay in screen even when finished
if (type == Type.FADE_IN)
reset();
-
+
if (cb != null) {
ActionCallback tmpcb = cb;
cb = null;
@@ -102,9 +102,12 @@ public void write(Json json) {
json.writeValue("time", time);
json.writeValue("color", c);
json.writeValue("type", type);
-
- if(cb != null)
- json.writeValue("cb", ActionCallbackSerializer.find(((BladeJson) json).getWorld(), cb));
+
+ if (cb != null) {
+ World w = ((BladeJson) json).getWorld();
+ Scene s = ((BladeJson) json).getScene();
+ json.writeValue("cb", ActionCallbackSerializer.find(w, s, cb));
+ }
}
@Override
@@ -113,6 +116,8 @@ public void read(Json json, JsonValue jsonData) {
time = json.readValue("time", Float.class, jsonData);
c = json.readValue("color", Color.class, jsonData);
type = json.readValue("type", Type.class, jsonData);
- cb = ActionCallbackSerializer.find(((BladeJson) json).getWorld(), json.readValue("cb", String.class, jsonData));
+ BladeJson bjson = (BladeJson) json;
+ cb = ActionCallbackSerializer.find(bjson.getWorld(), bjson.getScene(),
+ json.readValue("cb", String.class, jsonData));
}
}
diff --git a/blade-engine/src/com/bladecoder/engine/model/UIActors.java b/blade-engine/src/com/bladecoder/engine/model/UIActors.java
index 2351503ce..6bc9e6234 100644
--- a/blade-engine/src/com/bladecoder/engine/model/UIActors.java
+++ b/blade-engine/src/com/bladecoder/engine/model/UIActors.java
@@ -1,6 +1,7 @@
package com.bladecoder.engine.model;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import com.badlogic.gdx.graphics.Camera;
@@ -60,7 +61,11 @@ public List getActors() {
}
public void update(float delta) {
- for (InteractiveActor a : actors) {
+ // we use iterator because the actor can be deleted in the update.
+ Iterator i = actors.iterator();
+
+ while (i.hasNext()) {
+ InteractiveActor a = i.next();
a.update(delta);
}
}
@@ -94,9 +99,14 @@ public InteractiveActor getActorAtInput(Viewport v) {
cam.getInputUnProject(v, unprojectTmp);
+ return getActorAt(unprojectTmp.x, unprojectTmp.y);
+ }
+
+ public InteractiveActor getActorAt(float x, float y) {
for (InteractiveActor uia : actors) {
- if (uia.canInteract() && uia.hit(unprojectTmp.x, unprojectTmp.y))
+ if (uia.canInteract() && uia.hit(x, y)) {
return uia;
+ }
}
return null;
@@ -168,7 +178,6 @@ public void read(Json json, JsonValue jsonData) {
// to restore verb cb properly.
for (int i = 0; i < jsonValueActors.size; i++) {
JsonValue jsonValueAct = jsonValueActors.get(i);
- actorRef = new SceneActorRef(jsonValueAct.name);
InteractiveActor actor = actors.get(i);
actor.read(json, jsonValueAct);
diff --git a/blade-engine/src/com/bladecoder/engine/model/Verb.java b/blade-engine/src/com/bladecoder/engine/model/Verb.java
index 9bdde2918..c7ee2d246 100644
--- a/blade-engine/src/com/bladecoder/engine/model/Verb.java
+++ b/blade-engine/src/com/bladecoder/engine/model/Verb.java
@@ -47,7 +47,7 @@ public class Verb implements VerbRunner, Serializable {
private String target;
private String icon;
- private final ArrayList actions = new ArrayList();
+ private final ArrayList actions = new ArrayList<>();
private int ip = -1;
private String currentTarget;
@@ -109,14 +109,17 @@ public void add(Action a) {
actions.add(a);
}
+ @Override
public ArrayList getActions() {
return actions;
}
+ @Override
public String getCurrentTarget() {
return currentTarget;
}
+ @Override
public void run(String currentTarget, ActionCallback cb) {
this.currentTarget = currentTarget;
this.cb = cb;
@@ -151,8 +154,8 @@ public void nextStep() {
else
ip++;
} catch (Exception e) {
- EngineLogger.error(
- "EXCEPTION EXECUTING ACTION: " + a.getClass().getSimpleName() + " - " + e.getMessage(), e);
+ EngineLogger.error("EXCEPTION EXECUTING ACTION: " + id + " - " + ip + " - "
+ + a.getClass().getSimpleName() + " - " + e.getMessage(), e);
ip++;
}
}
@@ -179,14 +182,17 @@ public void resume() {
nextStep();
}
+ @Override
public int getIP() {
return ip;
}
+ @Override
public void setIP(int ip) {
this.ip = ip;
}
+ @Override
public void cancel() {
ip = actions.size() + 1;
@@ -228,9 +234,9 @@ public void write(Json json) {
json.writeArrayEnd();
} else {
json.writeValue("ip", ip);
-
- if(cb != null)
- json.writeValue("cb", ActionCallbackSerializer.find(bjson.getWorld(), cb));
+
+ if (cb != null)
+ json.writeValue("cb", ActionCallbackSerializer.find(bjson.getWorld(), bjson.getScene(), cb));
if (currentTarget != null)
json.writeValue("currentTarget", currentTarget);
@@ -275,7 +281,8 @@ public void read(Json json, JsonValue jsonData) {
// MUTABLE
currentTarget = json.readValue("currentTarget", String.class, (String) null, jsonData);
ip = json.readValue("ip", Integer.class, jsonData);
- cb = ActionCallbackSerializer.find(bjson.getWorld(), json.readValue("cb", String.class, jsonData));
+ cb = ActionCallbackSerializer.find(bjson.getWorld(), bjson.getScene(),
+ json.readValue("cb", String.class, jsonData));
JsonValue actionsValue = jsonData.get("actions");
diff --git a/blade-engine/src/com/bladecoder/engine/model/VoiceManager.java b/blade-engine/src/com/bladecoder/engine/model/VoiceManager.java
index d134ecc81..3f9b50aec 100644
--- a/blade-engine/src/com/bladecoder/engine/model/VoiceManager.java
+++ b/blade-engine/src/com/bladecoder/engine/model/VoiceManager.java
@@ -30,7 +30,7 @@ public class VoiceManager implements Serializable, AssetConsumer {
// the music volume
private float volume = 1.0f;
-
+
// the global configurable by user volume
public static float VOLUME_MULTIPLIER = 1f;
@@ -93,7 +93,7 @@ public void play(String fileName) {
// Load and play the voice file in background to avoid
// blocking the UI
loadAssets();
-
+
backgroundLoadingTask.cancel();
Timer.schedule(backgroundLoadingTask, 0, 0);
}
@@ -106,6 +106,10 @@ public void setVolume(float volume) {
voice.setVolume(volume * VOLUME_MULTIPLIER);
}
+ public float getVolume() {
+ return volume;
+ }
+
@Override
public void dispose() {
if (voice != null) {
diff --git a/blade-engine/src/com/bladecoder/engine/model/WalkZoneActor.java b/blade-engine/src/com/bladecoder/engine/model/WalkZoneActor.java
index a5343fb74..4e69f45a3 100644
--- a/blade-engine/src/com/bladecoder/engine/model/WalkZoneActor.java
+++ b/blade-engine/src/com/bladecoder/engine/model/WalkZoneActor.java
@@ -31,8 +31,9 @@ public class WalkZoneActor extends BaseActor {
public void update(float delta) {
}
+ @Override
public void setPosition(float x, float y) {
- bbox.setPosition(x, y);
+ getBBox().setPosition(x, y);
if (scene != null && id.equals(scene.getWalkZone())) {
scene.getPolygonalNavGraph().createInitialGraph(this, scene.getActors().values());
@@ -43,8 +44,8 @@ public void setPosition(float x, float y) {
public void write(Json json) {
BladeJson bjson = (BladeJson) json;
if (bjson.getMode() == Mode.MODEL) {
- PolygonUtils.ensureClockWise(bbox.getVertices(), 0, bbox.getVertices().length);
- bbox.dirty();
+ PolygonUtils.ensureClockWise(getBBox().getVertices(), 0, getBBox().getVertices().length);
+ getBBox().dirty();
}
super.write(json);
diff --git a/blade-engine/src/com/bladecoder/engine/model/World.java b/blade-engine/src/com/bladecoder/engine/model/World.java
index 455052c1b..b87d3dd8a 100644
--- a/blade-engine/src/com/bladecoder/engine/model/World.java
+++ b/blade-engine/src/com/bladecoder/engine/model/World.java
@@ -42,6 +42,7 @@
import com.badlogic.gdx.utils.viewport.Viewport;
import com.bladecoder.engine.assets.AssetConsumer;
import com.bladecoder.engine.assets.EngineAssetManager;
+import com.bladecoder.engine.i18n.I18N;
import com.bladecoder.engine.ink.InkManager;
import com.bladecoder.engine.serialization.WorldSerialization;
import com.bladecoder.engine.util.EngineLogger;
@@ -70,6 +71,7 @@ public static enum WorldProperties {
private final HashMap sounds = new HashMap<>();
private final HashMap scenes = new HashMap<>();
private final VerbManager verbs = new VerbManager();
+ private final I18N i18n = new I18N();
private Scene currentScene;
private Dialog currentDialog;
@@ -120,6 +122,10 @@ public static enum WorldProperties {
// If true call 'initNewGame' or 'initSavedGame' verbs.
private boolean initGame;
+ // The verb to call after loading a scene. If null, the "init" verb will be
+ // called
+ private String initVerb;
+
private final WorldSerialization serialization = new WorldSerialization(this);
public World() {
@@ -266,16 +272,29 @@ else if (customProperties.get(WorldProperties.SAVED_GAME_VERSION.toString()) !=
// call 'init' verb only when arrives from setCurrentScene and not
// from load or restoring
if (initScene) {
+ currentScene.init();
+
// If in test mode run 'test' verb (only the first time)
if (testScene != null && testScene.equals(currentScene.getId())
&& currentScene.getVerb(Verb.TEST_VERB) != null) {
- currentScene.runVerb(Verb.TEST_VERB);
+
+ initVerb = Verb.TEST_VERB;
+
testScene = null;
}
- currentScene.init();
+ if (initVerb == null)
+ initVerb = "init";
}
+ // Run INIT verb
+ if (initVerb != null && (currentScene.getVerb(initVerb) != null
+ || getVerbManager().getVerb(initVerb, null, null) != null)) {
+ currentScene.runVerb(initVerb);
+ }
+
+ initVerb = null;
+
}
if (paused || assetState != AssetState.LOADED)
@@ -348,6 +367,10 @@ public AssetState getAssetState() {
return assetState;
}
+ public I18N getI18N() {
+ return i18n;
+ }
+
public Dialog getCurrentDialog() {
return currentDialog;
}
@@ -368,7 +391,7 @@ public void setInitScene(String initScene) {
this.initScene = initScene;
}
- public void setCurrentScene(Scene scene, boolean init) {
+ public void setCurrentScene(Scene scene, boolean init, String initVerb) {
initLoadingTime = System.currentTimeMillis();
@@ -406,6 +429,7 @@ public void setCurrentScene(Scene scene, boolean init) {
}
currentScene = scene;
+ this.initVerb = initVerb;
musicManager.leaveScene(currentScene.getMusicDesc());
}
@@ -445,14 +469,14 @@ public void setCutMode(boolean v) {
listener.cutMode(cutMode);
}
- public void setCurrentScene(String id, boolean init) {
+ public void setCurrentScene(String id, boolean init, String initVerb) {
if (id.equals("$" + WorldProperties.PREVIOUS_SCENE.toString()))
id = getCustomProperty(WorldProperties.PREVIOUS_SCENE.toString());
Scene s = scenes.get(id);
if (s != null) {
- setCurrentScene(s, init);
+ setCurrentScene(s, init, initVerb);
} else {
EngineLogger.error("SetCurrentScene - COULD NOT FIND SCENE: " + id);
}
diff --git a/blade-engine/src/com/bladecoder/engine/polygonalpathfinder/PolygonalNavGraph.java b/blade-engine/src/com/bladecoder/engine/polygonalpathfinder/PolygonalNavGraph.java
index 036fe8fb0..dfc2aa112 100644
--- a/blade-engine/src/com/bladecoder/engine/polygonalpathfinder/PolygonalNavGraph.java
+++ b/blade-engine/src/com/bladecoder/engine/polygonalpathfinder/PolygonalNavGraph.java
@@ -42,17 +42,17 @@ public class PolygonalNavGraph implements NavGraph {
private static final Vector2 tmp2 = new Vector2();
private Polygon walkZone;
- private final ArrayList obstacles = new ArrayList();
+ private final ArrayList obstacles = new ArrayList<>();
- final private PathFinder pathfinder = new AStarPathFinder(this,
+ final private PathFinder pathfinder = new AStarPathFinder<>(this,
MAX_PATHFINDER_SEARCH_DISTANCE, new ManhattanDistance());
- final private NavPathPolygonal resultPath = new NavPathPolygonal();
+
final private NavNodePolygonal startNode = new NavNodePolygonal();
final private NavNodePolygonal targetNode = new NavNodePolygonal();
- final private ArrayList graphNodes = new ArrayList();
+ final private ArrayList graphNodes = new ArrayList<>();
public ArrayList findPath(float sx, float sy, float tx, float ty) {
- resultPath.clear();
+ final NavPathPolygonal resultPath = new NavPathPolygonal();
Vector2 source = new Vector2(sx, sy);
Vector2 target = new Vector2(tx, ty);
@@ -125,10 +125,8 @@ public ArrayList findPath(float sx, float sy, float tx, float ty) {
/**
* Search the first polygon vertex inside the walkzone.
*
- * @param p
- * the polygon
- * @param target
- * the vertex found
+ * @param p the polygon
+ * @param target the vertex found
*/
private void getFirstVertexInsideWalkzone(Polygon p, Vector2 target) {
float verts[] = p.getTransformedVertices();
@@ -145,12 +143,12 @@ private void getFirstVertexInsideWalkzone(Polygon p, Vector2 target) {
public void createInitialGraph(BaseActor wz, Collection actors) {
graphNodes.clear();
-
- if(wz == null) {
+
+ if (wz == null) {
walkZone = null;
return;
}
-
+
walkZone = wz.getBBox();
// 1.- Add WalkZone convex nodes
@@ -285,7 +283,7 @@ public void addDinamicObstacle(Polygon poly) {
int idx = obstacles.indexOf(poly);
// CHECK TO AVOID ADDING THE ACTOR SEVERAL TIMES
- if (idx == -1) {
+ if (idx == -1 && walkZone != null) {
obstacles.add(poly);
addObstacleToGrapth(poly);
}
diff --git a/blade-engine/src/com/bladecoder/engine/serialization/ActionCallbackSerializer.java b/blade-engine/src/com/bladecoder/engine/serialization/ActionCallbackSerializer.java
index 407806423..79b7de8e2 100644
--- a/blade-engine/src/com/bladecoder/engine/serialization/ActionCallbackSerializer.java
+++ b/blade-engine/src/com/bladecoder/engine/serialization/ActionCallbackSerializer.java
@@ -17,7 +17,7 @@
import com.bladecoder.engine.actions.Action;
import com.bladecoder.engine.actions.ActionCallback;
-import com.bladecoder.engine.ink.InkManager;
+import com.bladecoder.engine.ink.InkManager.InkVerbRunner;
import com.bladecoder.engine.model.BaseActor;
import com.bladecoder.engine.model.InteractiveActor;
import com.bladecoder.engine.model.Inventory;
@@ -115,12 +115,18 @@ private static String find(ActionCallback cb, Scene s) {
return null;
}
- private static String find(ActionCallback cb, InkManager im) {
+ private static String find(ActionCallback cb, InkVerbRunner im) {
if (im == null)
return null;
- if (cb instanceof InkManager)
- return INK_MANAGER_TAG;
+ if (cb instanceof InkVerbRunner) {
+ if (cb == im) {
+ return INK_MANAGER_TAG;
+ } else {
+ EngineLogger.debug("CB pointing to an old InkVerbRunner. IGNORING.");
+ return null;
+ }
+ }
int pos = 0;
@@ -175,11 +181,10 @@ private static String find(ActionCallback cb, Inventory inv) {
/**
* Generates a String for serialization that allows locate the ActionCallback
*
- * @param cb
- * The ActionCallback to serialize
+ * @param cb The ActionCallback to serialize
* @return The generated location string
*/
- public static String find(World w, ActionCallback cb) {
+ public static String find(World w, Scene s, ActionCallback cb) {
String id = null;
if (cb == null)
@@ -198,14 +203,14 @@ public static String find(World w, ActionCallback cb) {
return id;
// search in inkManager actions
- id = find(cb, w.getInkManager());
+ if (w.getInkManager() != null) {
+ id = find(cb, w.getInkManager().getVerbRunner());
+ }
if (id != null)
return id;
// search in scene verbs
- Scene s = w.getCurrentScene();
-
id = find(cb, s);
if (id != null)
@@ -245,21 +250,19 @@ public static String find(World w, ActionCallback cb) {
*
* @param id
*/
- public static ActionCallback find(World w, String id) {
+ public static ActionCallback find(World w, Scene s, String id) {
if (id == null)
return null;
- Scene s = w.getCurrentScene();
-
String[] split = id.split(SEPARATION_SYMBOL);
if (id.startsWith(INK_MANAGER_TAG)) {
if (split.length == 1)
- return w.getInkManager();
+ return w.getInkManager().getVerbRunner();
int actionPos = Integer.parseInt(split[1]);
- Action action = w.getInkManager().getActions().get(actionPos);
+ Action action = w.getInkManager().getVerbRunner().getActions().get(actionPos);
if (action instanceof ActionCallback)
return (ActionCallback) action;
diff --git a/blade-engine/src/com/bladecoder/engine/serialization/BladeJson.java b/blade-engine/src/com/bladecoder/engine/serialization/BladeJson.java
index 04cf390d8..9fd280883 100644
--- a/blade-engine/src/com/bladecoder/engine/serialization/BladeJson.java
+++ b/blade-engine/src/com/bladecoder/engine/serialization/BladeJson.java
@@ -1,6 +1,23 @@
package com.bladecoder.engine.serialization;
import com.badlogic.gdx.utils.Json;
+import com.badlogic.gdx.utils.ObjectMap;
+import com.bladecoder.engine.actions.Action;
+import com.bladecoder.engine.actions.ActionFactory;
+import com.bladecoder.engine.anim.AtlasAnimationDesc;
+import com.bladecoder.engine.anim.SpineAnimationDesc;
+import com.bladecoder.engine.model.AnchorActor;
+import com.bladecoder.engine.model.AtlasRenderer;
+import com.bladecoder.engine.model.CharacterActor;
+import com.bladecoder.engine.model.ImageRenderer;
+import com.bladecoder.engine.model.InteractiveActor;
+import com.bladecoder.engine.model.ObstacleActor;
+import com.bladecoder.engine.model.ParticleRenderer;
+import com.bladecoder.engine.model.Scene;
+import com.bladecoder.engine.model.Sprite3DRenderer;
+import com.bladecoder.engine.model.SpriteActor;
+import com.bladecoder.engine.model.TextRenderer;
+import com.bladecoder.engine.model.WalkZoneActor;
import com.bladecoder.engine.model.World;
/**
@@ -18,12 +35,39 @@ public enum Mode {
private final Mode mode;
private boolean init;
+ // the scene being saved
+ private Scene scene;
+
public BladeJson(World w, Mode mode, boolean init) {
super();
this.w = w;
this.mode = mode;
this.init = init;
+
+ // Add tags for known classes to reduce .json size.
+ addClassTag(SpineAnimationDesc.class);
+ addClassTag(AtlasAnimationDesc.class);
+
+ addClassTag(CharacterActor.class);
+ addClassTag(AnchorActor.class);
+ addClassTag(ObstacleActor.class);
+ addClassTag(InteractiveActor.class);
+ addClassTag(SpriteActor.class);
+ addClassTag(WalkZoneActor.class);
+
+ addClassTag(AtlasRenderer.class);
+ addClassTag(ImageRenderer.class);
+ addClassTag(ParticleRenderer.class);
+ addClassTag(Sprite3DRenderer.class);
+ addClassTag(TextRenderer.class);
+
+ ObjectMap> classTags = ActionFactory.getClassTags();
+
+ for (ObjectMap.Entry> e : classTags.entries()) {
+ addClassTag(e.key, e.value);
+ }
+
}
public BladeJson(World w, Mode mode) {
@@ -45,4 +89,16 @@ public boolean getInit() {
public void setInit(boolean init) {
this.init = init;
}
+
+ public Scene getScene() {
+ return scene == null ? w.getCurrentScene() : scene;
+ }
+
+ public void setScene(Scene scene) {
+ this.scene = scene;
+ }
+
+ public void addClassTag(Class> tag) {
+ addClassTag(tag.getSimpleName(), tag);
+ }
}
diff --git a/blade-engine/src/com/bladecoder/engine/serialization/WorldSerialization.java b/blade-engine/src/com/bladecoder/engine/serialization/WorldSerialization.java
index 17f32af4b..5e935737c 100644
--- a/blade-engine/src/com/bladecoder/engine/serialization/WorldSerialization.java
+++ b/blade-engine/src/com/bladecoder/engine/serialization/WorldSerialization.java
@@ -6,6 +6,8 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
@@ -21,7 +23,6 @@
import com.bladecoder.engine.actions.SoundAction;
import com.bladecoder.engine.anim.AnimationDesc;
import com.bladecoder.engine.assets.EngineAssetManager;
-import com.bladecoder.engine.i18n.I18N;
import com.bladecoder.engine.model.AnimationRenderer;
import com.bladecoder.engine.model.BaseActor;
import com.bladecoder.engine.model.CharacterActor;
@@ -40,7 +41,7 @@
@SuppressWarnings("deprecation")
public class WorldSerialization implements Serializable {
- public static final String GAMESTATE_EXT = ".gamestate.v13";
+ public static final String GAMESTATE_EXT = ".gamestate.v14";
private static final int SCREENSHOT_DEFAULT_WIDTH = 300;
@@ -88,7 +89,7 @@ public void loadWorldDesc() throws IOException {
w.setHeight((int) (height * scale));
w.setInitChapter(json.readValue("initChapter", String.class, root));
w.getVerbManager().read(json, root);
- I18N.loadWorld(EngineAssetManager.MODEL_DIR + EngineAssetManager.WORLD_FILENAME);
+ w.getI18N().loadWorld(EngineAssetManager.MODEL_DIR + EngineAssetManager.WORLD_FILENAME);
}
public void saveWorldDesc(FileHandle file) throws IOException {
@@ -154,11 +155,11 @@ public void loadChapter(String chapterName, String scene, boolean initScene) thr
read(json, root);
if (scene == null)
- w.setCurrentScene(w.getScenes().get(w.getInitScene()), initScene);
+ w.setCurrentScene(w.getScenes().get(w.getInitScene()), initScene, null);
else
- w.setCurrentScene(w.getScenes().get(scene), initScene);
+ w.setCurrentScene(w.getScenes().get(scene), initScene, null);
- I18N.loadChapter(EngineAssetManager.MODEL_DIR + chapterName);
+ w.getI18N().loadChapter(EngineAssetManager.MODEL_DIR + chapterName);
w.getCustomProperties().put(WorldProperties.CURRENT_CHAPTER.toString(), chapterName);
w.getCustomProperties().put(WorldProperties.PLATFORM.toString(), Gdx.app.getType().toString());
@@ -227,6 +228,7 @@ public void saveGameState(String filename, boolean screenshot) throws IOExceptio
Json json = new BladeJson(w, Mode.STATE);
json.setOutputType(OutputType.javascript);
+ json.setSortFields(true);
String s = null;
@@ -255,16 +257,27 @@ public void saveGameState(String filename, boolean screenshot) throws IOExceptio
public void write(Json json) {
BladeJson bjson = (BladeJson) json;
- json.writeValue(Config.BLADE_ENGINE_VERSION_PROP, Config.getProperty(Config.BLADE_ENGINE_VERSION_PROP, null));
+ json.writeValue(Config.BLADE_ENGINE_VERSION_PROP,
+ Config.getInstance().getProperty(Config.BLADE_ENGINE_VERSION_PROP, null));
if (bjson.getMode() == Mode.MODEL) {
- json.writeValue("sounds", w.getSounds(), w.getSounds().getClass(), SoundDesc.class);
- json.writeValue("scenes", w.getScenes(), w.getScenes().getClass(), Scene.class);
+ SortedMap sortedSounds = new TreeMap<>();
+ sortedSounds.putAll(w.getSounds());
+ json.writeValue("sounds", sortedSounds, sortedSounds.getClass(), SoundDesc.class);
+
+ SortedMap sortedScenes = new TreeMap<>();
+ sortedScenes.putAll(w.getScenes());
+ json.writeValue("scenes", sortedScenes, sortedScenes.getClass(), Scene.class);
+
json.writeValue("initScene", w.getInitScene());
} else {
- json.writeValue(Config.VERSION_PROP, Config.getProperty(Config.VERSION_PROP, null));
- json.writeValue("scenes", w.getScenes(), w.getScenes().getClass(), Scene.class);
+ json.writeValue(Config.VERSION_PROP, Config.getInstance().getProperty(Config.VERSION_PROP, null));
+
+ SortedMap sortedScenes = new TreeMap<>();
+ sortedScenes.putAll(w.getScenes());
+ json.writeValue("scenes", sortedScenes, sortedScenes.getClass(), Scene.class);
+
json.writeValue("currentScene", w.getCurrentScene().getId());
json.writeValue("inventories", w.getInventories());
json.writeValue("currentInventory", w.getCurrentInventory());
@@ -301,9 +314,9 @@ public void read(Json json, JsonValue jsonData) {
BladeJson bjson = (BladeJson) json;
if (bjson.getMode() == Mode.MODEL) {
if (bladeVersion != null
- && !bladeVersion.equals(Config.getProperty(Config.BLADE_ENGINE_VERSION_PROP, ""))) {
+ && !bladeVersion.equals(Config.getInstance().getProperty(Config.BLADE_ENGINE_VERSION_PROP, ""))) {
EngineLogger.debug("Model Engine Version v" + bladeVersion + " differs from Current Engine Version v"
- + Config.getProperty(Config.BLADE_ENGINE_VERSION_PROP, ""));
+ + Config.getInstance().getProperty(Config.BLADE_ENGINE_VERSION_PROP, ""));
}
// SOUNDS
@@ -348,10 +361,10 @@ public void read(Json json, JsonValue jsonData) {
cacheSounds();
} else {
if (bladeVersion != null
- && !bladeVersion.equals(Config.getProperty(Config.BLADE_ENGINE_VERSION_PROP, ""))) {
+ && !bladeVersion.equals(Config.getInstance().getProperty(Config.BLADE_ENGINE_VERSION_PROP, ""))) {
EngineLogger
.debug("Saved Game Engine Version v" + bladeVersion + " differs from Current Engine Version v"
- + Config.getProperty(Config.BLADE_ENGINE_VERSION_PROP, ""));
+ + Config.getInstance().getProperty(Config.BLADE_ENGINE_VERSION_PROP, ""));
}
String currentChapter = json.readValue("chapter", String.class, jsonData);
@@ -426,7 +439,7 @@ public void read(Json json, JsonValue jsonData) {
w.getTransition().read(json, jsonData.get("transition"));
w.getMusicManager().read(json, jsonData.get("musicEngine"));
- I18N.loadChapter(EngineAssetManager.MODEL_DIR + w.getCurrentChapter());
+ w.getI18N().loadChapter(EngineAssetManager.MODEL_DIR + w.getCurrentChapter());
}
}
@@ -449,16 +462,25 @@ private void cacheSounds() {
String actor = ActionUtils.getStringValue(act, "actor");
String play = ActionUtils.getStringValue(act, "play");
if (play != null) {
+
+ if (actor.equals("$PLAYER"))
+ actor = s.getPlayer().getId();
+
SoundDesc sd = w.getSounds().get(actor + "_" + play);
- if (sd != null)
- s.getSoundManager().addSoundToLoad(sd);
+ if (sd == null) {
+ EngineLogger.error(
+ "Reference to sound not found: " + s.getId() + "." + actor + "." + play);
+ continue;
+ }
+
+ s.getSoundManager().addSoundToLoad(sd);
HashMap params = new HashMap<>();
params.put("sound", sd.getId());
try {
- Action a2 = ActionFactory.createByClass(PlaySoundAction.class.getName(), params);
+ Action a2 = ActionFactory.create(PlaySoundAction.class.getName(), params);
actions.set(i, a2);
a2.init(w);
} catch (ClassNotFoundException | ReflectionException e) {
@@ -500,18 +522,26 @@ private void cacheSounds() {
String actor = ActionUtils.getStringValue(act, "actor");
String play = ActionUtils.getStringValue(act, "play");
+
if (play != null) {
+ if ("$PLAYER".equals(actor))
+ actor = s.getPlayer().getId();
+
SoundDesc sd = w.getSounds().get(actor + "_" + play);
- if (sd != null)
- s.getSoundManager().addSoundToLoad(sd);
+ if (sd == null) {
+ EngineLogger.error("Reference to sound not found: " + s.getId() + "."
+ + actor + "." + play);
+ continue;
+ }
+
+ s.getSoundManager().addSoundToLoad(sd);
HashMap params = new HashMap<>();
params.put("sound", sd.getId());
try {
- Action a2 = ActionFactory.createByClass(PlaySoundAction.class.getName(),
- params);
+ Action a2 = ActionFactory.create(PlaySoundAction.class.getName(), params);
actions.set(i, a2);
a2.init(w);
} catch (ClassNotFoundException | ReflectionException e) {
diff --git a/blade-engine/src/com/bladecoder/engine/ui/AnimButton.java b/blade-engine/src/com/bladecoder/engine/ui/AnimButton.java
new file mode 100644
index 000000000..fa0f36986
--- /dev/null
+++ b/blade-engine/src/com/bladecoder/engine/ui/AnimButton.java
@@ -0,0 +1,29 @@
+package com.bladecoder.engine.ui;
+
+import com.badlogic.gdx.scenes.scene2d.ui.Button;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+
+public class AnimButton extends Button {
+ public AnimButton(Skin skin, String styleName) {
+ super(skin, styleName);
+ }
+
+ public AnimButton(ButtonStyle style) {
+ super(style);
+ }
+
+ @Override
+ public void act(float delta) {
+ ButtonStyle style = getStyle();
+ if (style.up != null && style.up instanceof AnimationDrawable)
+ ((AnimationDrawable) style.up).act(delta);
+
+ if (style.over != null && style.over instanceof AnimationDrawable)
+ ((AnimationDrawable) style.over).act(delta);
+
+ if (style.down != null && style.down instanceof AnimationDrawable)
+ ((AnimationDrawable) style.down).act(delta);
+
+ super.act(delta);
+ }
+}
diff --git a/blade-engine/src/com/bladecoder/engine/ui/AnimationDrawable.java b/blade-engine/src/com/bladecoder/engine/ui/AnimationDrawable.java
new file mode 100644
index 000000000..1e0cfe66e
--- /dev/null
+++ b/blade-engine/src/com/bladecoder/engine/ui/AnimationDrawable.java
@@ -0,0 +1,75 @@
+package com.bladecoder.engine.ui;
+
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.g2d.Animation;
+import com.badlogic.gdx.graphics.g2d.Animation.PlayMode;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
+import com.badlogic.gdx.scenes.scene2d.utils.BaseDrawable;
+import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
+import com.badlogic.gdx.scenes.scene2d.utils.TransformDrawable;
+
+public class AnimationDrawable extends BaseDrawable implements TransformDrawable {
+ public final Animation anim;
+ private float stateTime = 0;
+ private Color tint;
+
+ public AnimationDrawable(Animation anim) {
+ this.anim = anim;
+ setMinWidth(anim.getKeyFrames()[0].getRegionWidth());
+ setMinHeight(anim.getKeyFrames()[0].getRegionHeight());
+ }
+
+ public AnimationDrawable(AnimationDrawable ad) {
+ super(ad);
+ anim = new Animation(ad.getAnimation().getFrameDuration(), ad.getAnimation().getKeyFrames());
+ anim.setPlayMode(PlayMode.LOOP);
+ }
+
+ public void act(float delta) {
+ stateTime += delta;
+ }
+
+ public void reset() {
+ stateTime = 0;
+ }
+
+ @Override
+ public void draw(Batch batch, float x, float y, float width, float height) {
+ if (tint != null)
+ batch.setColor(tint);
+
+ batch.draw(anim.getKeyFrame(stateTime), x, y, width, height);
+
+ if (tint != null)
+ batch.setColor(Color.WHITE);
+ }
+
+ @Override
+ public void draw(Batch batch, float x, float y, float originX, float originY, float width, float height,
+ float scaleX, float scaleY, float rotation) {
+
+ if (tint != null)
+ batch.setColor(tint);
+
+ batch.draw(anim.getKeyFrame(stateTime), x, y, originX, originY, width, height, scaleX, scaleY, rotation);
+
+ if (tint != null)
+ batch.setColor(Color.WHITE);
+ }
+
+ public Animation getAnimation() {
+ return anim;
+ }
+
+ public Drawable tint(Color tint) {
+ AnimationDrawable d = new AnimationDrawable(this);
+ d.setTint(tint);
+
+ return d;
+ }
+
+ public void setTint(Color t) {
+ this.tint = t;
+ }
+}
diff --git a/blade-engine/src/com/bladecoder/engine/ui/BladeSkin.java b/blade-engine/src/com/bladecoder/engine/ui/BladeSkin.java
index afbb006ff..612ec56d1 100644
--- a/blade-engine/src/com/bladecoder/engine/ui/BladeSkin.java
+++ b/blade-engine/src/com/bladecoder/engine/ui/BladeSkin.java
@@ -3,13 +3,18 @@
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.g2d.Animation;
+import com.badlogic.gdx.graphics.g2d.Animation.PlayMode;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.utils.BaseDrawable;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
+import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.Json.ReadOnlySerializer;
import com.badlogic.gdx.utils.JsonValue;
@@ -111,6 +116,7 @@ public BitmapFont read(Json json, JsonValue jsonData, @SuppressWarnings("rawtype
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(fontFile);
FreeTypeFontParameter parameter = new FreeTypeFontParameter();
parameter.size = (int) (DPIUtils.dpToPixels(size) * DPIUtils.getSizeMultiplier());
+ parameter.color = json.readValue("color", Color.class, Color.WHITE, jsonData);
parameter.incremental = json.readValue("incremental", boolean.class, true, jsonData);
parameter.borderWidth = json.readValue("borderWidth", int.class, 0, jsonData);
parameter.borderColor = json.readValue("borderColor", Color.class, Color.BLACK, jsonData);
@@ -166,10 +172,63 @@ else if (size != -1) // TODO set size in points (dpi
}
});
+ json.setSerializer(AnimationDrawable.class, new ReadOnlySerializer