diff --git a/maps-basic/src/com/mobidevelop/maps/basic/BasicMap.java b/maps-basic/src/com/mobidevelop/maps/basic/BasicMap.java
index 1b62775..76ace4e 100644
--- a/maps-basic/src/com/mobidevelop/maps/basic/BasicMap.java
+++ b/maps-basic/src/com/mobidevelop/maps/basic/BasicMap.java
@@ -1,6 +1,7 @@
package com.mobidevelop.maps.basic;
import com.mobidevelop.maps.Map;
+import com.mobidevelop.maps.MapLayer;
import com.mobidevelop.maps.MapLayers;
import com.mobidevelop.maps.MapProperties;
import com.mobidevelop.maps.MapResources;
@@ -110,5 +111,12 @@ public BasicMap(float x, float y, float width, float height) {
public void dispose() {
resources.dispose();
}
-
+
+ @Override
+ public MapLayer createLayer( String name ) {
+
+ BasicMapLayer layer = new BasicMapLayer( this );
+ layer.setName( name );
+ return layer;
+ }
}
diff --git a/maps-basic/src/com/mobidevelop/maps/brush/ImageBrushMapObject.java b/maps-basic/src/com/mobidevelop/maps/brush/ImageBrushMapObject.java
new file mode 100644
index 0000000..650b465
--- /dev/null
+++ b/maps-basic/src/com/mobidevelop/maps/brush/ImageBrushMapObject.java
@@ -0,0 +1,22 @@
+package com.mobidevelop.maps.brush;
+
+import com.mobidevelop.maps.MapLayer;
+import com.mobidevelop.maps.basic.BasicMapObject;
+
+
+public class ImageBrushMapObject extends BasicMapObject {
+
+ private String imageName;
+
+ public ImageBrushMapObject( MapLayer layer, float x, float y, String imageName ) {
+
+ super( layer, x, y );
+
+ this.imageName = imageName;
+ }
+
+ public String getImageName() {
+
+ return imageName;
+ }
+}
diff --git a/maps-editor-android/assets/data/uiskin.atlas b/maps-editor-android/assets/data/uiskin.atlas
index c193581..84d7f47 100644
--- a/maps-editor-android/assets/data/uiskin.atlas
+++ b/maps-editor-android/assets/data/uiskin.atlas
@@ -3,6 +3,35 @@ uiskin.png
format: RGBA8888
filter: Nearest,Nearest
repeat: none
+check-off
+ rotate: false
+ xy: 11, 5
+ size: 14, 14
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+textfield
+ rotate: false
+ xy: 11, 5
+ size: 14, 14
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+check-on
+ rotate: false
+ xy: 125, 35
+ size: 14, 14
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+cursor
+ rotate: false
+ xy: 23, 1
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
default
rotate: false
xy: 1, 50
@@ -10,51 +39,44 @@ default
orig: 254, 77
offset: 0, 0
index: -1
-default-window
- rotate: false
- xy: 1, 20
- size: 27, 29
- split: 4, 3, 20, 3
- orig: 27, 29
- offset: 0, 0
- index: -1
-default-select
+default-pane
rotate: false
- xy: 29, 29
- size: 27, 20
- split: 4, 14, 4, 4
- orig: 27, 20
+ xy: 11, 1
+ size: 5, 3
+ split: 1, 1, 1, 1
+ orig: 5, 3
offset: 0, 0
index: -1
-default-round-large
+default-rect-pad
rotate: false
- xy: 57, 29
- size: 20, 20
- split: 5, 5, 5, 4
- orig: 20, 20
+ xy: 11, 1
+ size: 5, 3
+ split: 1, 1, 1, 1
+ orig: 5, 3
offset: 0, 0
index: -1
-default-scroll
+default-pane-noborder
rotate: false
- xy: 78, 29
- size: 20, 20
- split: 2, 2, 2, 2
- orig: 20, 20
+ xy: 129, 33
+ size: 1, 1
+ split: 0, 0, 0, 0
+ orig: 1, 1
offset: 0, 0
index: -1
-default-slider-knob
+default-rect
rotate: false
- xy: 1, 1
- size: 9, 18
- orig: 9, 18
+ xy: 38, 25
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
offset: 0, 0
index: -1
-default-round-down
+default-rect-down
rotate: false
- xy: 99, 29
- size: 12, 20
- split: 5, 5, 5, 4
- orig: 12, 20
+ xy: 170, 46
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
offset: 0, 0
index: -1
default-round
@@ -66,40 +88,44 @@ default-round
orig: 12, 20
offset: 0, 0
index: -1
-check-off
+default-round-down
rotate: false
- xy: 11, 5
- size: 14, 14
- orig: 14, 14
+ xy: 99, 29
+ size: 12, 20
+ split: 5, 5, 5, 4
+ orig: 12, 20
offset: 0, 0
index: -1
-textfield
+default-round-large
rotate: false
- xy: 11, 5
- size: 14, 14
- split: 3, 3, 3, 3
- orig: 14, 14
+ xy: 57, 29
+ size: 20, 20
+ split: 5, 5, 5, 4
+ orig: 20, 20
offset: 0, 0
index: -1
-check-on
+default-scroll
rotate: false
- xy: 125, 35
- size: 14, 14
- orig: 14, 14
+ xy: 78, 29
+ size: 20, 20
+ split: 2, 2, 2, 2
+ orig: 20, 20
offset: 0, 0
index: -1
-tree-minus
+default-select
rotate: false
- xy: 140, 35
- size: 14, 14
- orig: 14, 14
+ xy: 29, 29
+ size: 27, 20
+ split: 4, 14, 4, 4
+ orig: 27, 20
offset: 0, 0
index: -1
-tree-plus
+default-select-selection
rotate: false
- xy: 155, 35
- size: 14, 14
- orig: 14, 14
+ xy: 26, 16
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
offset: 0, 0
index: -1
default-slider
@@ -110,20 +136,11 @@ default-slider
orig: 8, 8
offset: 0, 0
index: -1
-default-pane
- rotate: false
- xy: 11, 1
- size: 5, 3
- split: 1, 1, 1, 1
- orig: 5, 3
- offset: 0, 0
- index: -1
-default-rect-pad
+default-slider-knob
rotate: false
- xy: 11, 1
- size: 5, 3
- split: 1, 1, 1, 1
- orig: 5, 3
+ xy: 1, 1
+ size: 9, 18
+ orig: 9, 18
offset: 0, 0
index: -1
default-splitpane
@@ -134,14 +151,6 @@ default-splitpane
orig: 5, 3
offset: 0, 0
index: -1
-cursor
- rotate: false
- xy: 23, 1
- size: 3, 3
- split: 1, 1, 1, 1
- orig: 3, 3
- offset: 0, 0
- index: -1
default-splitpane-vertical
rotate: false
xy: 125, 29
@@ -150,43 +159,33 @@ default-splitpane-vertical
orig: 3, 5
offset: 0, 0
index: -1
-default-rect-down
- rotate: false
- xy: 170, 46
- size: 3, 3
- split: 1, 1, 1, 1
- orig: 3, 3
- offset: 0, 0
- index: -1
-default-rect
+default-window
rotate: false
- xy: 38, 25
- size: 3, 3
- split: 1, 1, 1, 1
- orig: 3, 3
+ xy: 1, 20
+ size: 27, 29
+ split: 4, 3, 20, 3
+ orig: 27, 29
offset: 0, 0
index: -1
-default-select-selection
+selection
rotate: false
- xy: 26, 16
- size: 3, 3
- split: 1, 1, 1, 1
- orig: 3, 3
+ xy: 170, 44
+ size: 1, 1
+ orig: 1, 1
offset: 0, 0
index: -1
-default-pane-noborder
+tree-minus
rotate: false
- xy: 129, 33
- size: 1, 1
- split: 0, 0, 0, 0
- orig: 1, 1
+ xy: 140, 35
+ size: 14, 14
+ orig: 14, 14
offset: 0, 0
index: -1
-selection
+tree-plus
rotate: false
- xy: 170, 44
- size: 1, 1
- orig: 1, 1
+ xy: 155, 35
+ size: 14, 14
+ orig: 14, 14
offset: 0, 0
index: -1
white
diff --git a/maps-editor-android/assets/data/uiskin.json b/maps-editor-android/assets/data/uiskin.json
index 551e3f5..2dd0a5a 100644
--- a/maps-editor-android/assets/data/uiskin.json
+++ b/maps-editor-android/assets/data/uiskin.json
@@ -39,7 +39,8 @@ com.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: {
default-horizontal: { background: default-slider, knob: default-slider-knob }
},
com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {
- default: { font: default-font, fontColor: white }
+ default: { font: default-font, fontColor: white },
+ selected: { background: selection, font: default-font, fontColor: white }
},
com.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: {
default: { selection: selection, background: textfield, font: default-font, fontColor: white, cursor: cursor }
diff --git a/maps-editor-android/assets/data/uiskin.png b/maps-editor-android/assets/data/uiskin.png
index f51c5bd..336fff8 100644
Binary files a/maps-editor-android/assets/data/uiskin.png and b/maps-editor-android/assets/data/uiskin.png differ
diff --git a/maps-editor/.classpath b/maps-editor/.classpath
index 5ded48f..de9306d 100644
--- a/maps-editor/.classpath
+++ b/maps-editor/.classpath
@@ -1,9 +1,10 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/maps-editor/assets-raw/skin/check-off.png b/maps-editor/assets-raw/skin/check-off.png
new file mode 100644
index 0000000..14b6512
Binary files /dev/null and b/maps-editor/assets-raw/skin/check-off.png differ
diff --git a/maps-editor/assets-raw/skin/check-on.png b/maps-editor/assets-raw/skin/check-on.png
new file mode 100644
index 0000000..5d21b76
Binary files /dev/null and b/maps-editor/assets-raw/skin/check-on.png differ
diff --git a/maps-editor/assets-raw/skin/cursor.9.png b/maps-editor/assets-raw/skin/cursor.9.png
new file mode 100644
index 0000000..aeed93c
Binary files /dev/null and b/maps-editor/assets-raw/skin/cursor.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-pane-noborder.9.png b/maps-editor/assets-raw/skin/default-pane-noborder.9.png
new file mode 100644
index 0000000..d2c3e66
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-pane-noborder.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-pane.9.png b/maps-editor/assets-raw/skin/default-pane.9.png
new file mode 100644
index 0000000..6b3f904
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-pane.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-rect-down.9.png b/maps-editor/assets-raw/skin/default-rect-down.9.png
new file mode 100644
index 0000000..81a63e0
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-rect-down.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-rect-pad.9.png b/maps-editor/assets-raw/skin/default-rect-pad.9.png
new file mode 100644
index 0000000..6b3f904
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-rect-pad.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-rect.9.png b/maps-editor/assets-raw/skin/default-rect.9.png
new file mode 100644
index 0000000..f1f5363
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-rect.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-round-down.9.png b/maps-editor/assets-raw/skin/default-round-down.9.png
new file mode 100644
index 0000000..f1616a3
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-round-down.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-round-large.9.png b/maps-editor/assets-raw/skin/default-round-large.9.png
new file mode 100644
index 0000000..ffc12fd
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-round-large.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-round.9.png b/maps-editor/assets-raw/skin/default-round.9.png
new file mode 100644
index 0000000..adf9568
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-round.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-scroll.9.png b/maps-editor/assets-raw/skin/default-scroll.9.png
new file mode 100644
index 0000000..832c1a3
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-scroll.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-select-selection.9.png b/maps-editor/assets-raw/skin/default-select-selection.9.png
new file mode 100644
index 0000000..4649412
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-select-selection.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-select.9.png b/maps-editor/assets-raw/skin/default-select.9.png
new file mode 100644
index 0000000..38b951a
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-select.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-slider-knob.png b/maps-editor/assets-raw/skin/default-slider-knob.png
new file mode 100644
index 0000000..e03d374
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-slider-knob.png differ
diff --git a/maps-editor/assets-raw/skin/default-slider.9.png b/maps-editor/assets-raw/skin/default-slider.9.png
new file mode 100644
index 0000000..5d7a781
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-slider.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-splitpane-vertical.9.png b/maps-editor/assets-raw/skin/default-splitpane-vertical.9.png
new file mode 100644
index 0000000..f6cffa3
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-splitpane-vertical.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-splitpane.9.png b/maps-editor/assets-raw/skin/default-splitpane.9.png
new file mode 100644
index 0000000..bd72370
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-splitpane.9.png differ
diff --git a/maps-editor/assets-raw/skin/default-window.9.png b/maps-editor/assets-raw/skin/default-window.9.png
new file mode 100644
index 0000000..0db9e67
Binary files /dev/null and b/maps-editor/assets-raw/skin/default-window.9.png differ
diff --git a/maps-editor/assets-raw/skin/default.png b/maps-editor/assets-raw/skin/default.png
new file mode 100644
index 0000000..e203acc
Binary files /dev/null and b/maps-editor/assets-raw/skin/default.png differ
diff --git a/maps-editor/assets-raw/skin/pack.json b/maps-editor/assets-raw/skin/pack.json
new file mode 100644
index 0000000..749d207
--- /dev/null
+++ b/maps-editor/assets-raw/skin/pack.json
@@ -0,0 +1,5 @@
+{
+duplicatePadding: false,
+paddingX: 1,
+paddingY: 1
+}
\ No newline at end of file
diff --git a/maps-editor/assets-raw/skin/selection.png b/maps-editor/assets-raw/skin/selection.png
new file mode 100644
index 0000000..d2533cb
Binary files /dev/null and b/maps-editor/assets-raw/skin/selection.png differ
diff --git a/maps-editor/assets-raw/skin/textfield.9.png b/maps-editor/assets-raw/skin/textfield.9.png
new file mode 100644
index 0000000..cb8ad31
Binary files /dev/null and b/maps-editor/assets-raw/skin/textfield.9.png differ
diff --git a/maps-editor/assets-raw/skin/tree-minus.png b/maps-editor/assets-raw/skin/tree-minus.png
new file mode 100644
index 0000000..f8e4079
Binary files /dev/null and b/maps-editor/assets-raw/skin/tree-minus.png differ
diff --git a/maps-editor/assets-raw/skin/tree-plus.png b/maps-editor/assets-raw/skin/tree-plus.png
new file mode 100644
index 0000000..85d23cc
Binary files /dev/null and b/maps-editor/assets-raw/skin/tree-plus.png differ
diff --git a/maps-editor/assets-raw/skin/white.png b/maps-editor/assets-raw/skin/white.png
new file mode 100644
index 0000000..bbad125
Binary files /dev/null and b/maps-editor/assets-raw/skin/white.png differ
diff --git a/maps-editor/src/BuildAssets.java b/maps-editor/src/BuildAssets.java
new file mode 100644
index 0000000..4cef110
--- /dev/null
+++ b/maps-editor/src/BuildAssets.java
@@ -0,0 +1,11 @@
+import com.badlogic.gdx.tools.imagepacker.TexturePacker2;
+
+
+public class BuildAssets {
+
+ public static void main( String[] args ) {
+
+// Settings settings = new Settings();
+ TexturePacker2.process( "assets-raw/skin", "../maps-editor-android/assets/data", "uiskin.atlas" );
+ }
+}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/LevelStage.java b/maps-editor/src/com/mobidevelop/maps/editor/LevelStage.java
new file mode 100644
index 0000000..0c2ce1f
--- /dev/null
+++ b/maps-editor/src/com/mobidevelop/maps/editor/LevelStage.java
@@ -0,0 +1,227 @@
+package com.mobidevelop.maps.editor;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input.Buttons;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.OrthographicCamera;
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Pixmap.Format;
+import com.badlogic.gdx.graphics.Texture.TextureFilter;
+import com.badlogic.gdx.graphics.g2d.PixmapPacker;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.Group;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.utils.SnapshotArray;
+import com.mobidevelop.maps.MapLayer;
+import com.mobidevelop.maps.MapObject;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerAddedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerHiddenEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerRemovedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerSelectedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerShownEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapObjectsModel.ObjectAddedEvent;
+import com.mobidevelop.maps.editor.ui.UIEvents;
+import com.mobidevelop.utils.events.Event;
+import com.mobidevelop.utils.events.EventDispatcher;
+import com.mobidevelop.utils.events.EventListener;
+
+
+public class LevelStage extends Stage implements EventListener {
+
+
+ private PixmapPacker imagePacker = null;
+ private TextureAtlas imageAtlas;
+
+ private Group layers;
+
+ private OrthographicCamera camera;
+ private Vector2 worldspaceCenter = new Vector2();
+ int lastX, lastY;
+ Vector3 vec3 = new Vector3();
+
+ public LevelStage( float width, float height, SpriteBatch batch ) {
+
+ super( width, height, true, batch );
+
+ // imagePacker packs added image resources into an atlas for stage rendering
+ imagePacker = new PixmapPacker( 1024, 1024, Format.RGBA8888, 2, false );
+ imageAtlas = new TextureAtlas();
+
+ layers = new Group();
+ addActor( layers );
+
+ camera = new OrthographicCamera( width, height );
+ setCamera( camera );
+ }
+
+ // handles camera controls
+ @Override
+ public boolean touchDown( int screenX, int screenY, int pointer, int button ) {
+
+ lastX = screenX;
+ lastY = screenY;
+ if ( Gdx.input.isButtonPressed( Buttons.LEFT ) ) {
+ Actor selected = layers.hit( screenX, screenY, false );
+ if ( selected != null ) {
+ if ( selected instanceof StageObject )
+ selected.fire( UIEvents.selectObject( ((StageObject)selected).getMapObject() ) );
+ }
+ }
+ return super.touchDown( screenX, screenY, pointer, button );
+ }
+
+ // handles camera controls
+ @Override
+ public boolean touchDragged( int screenX, int screenY, int pointer ) {
+
+ if ( Gdx.input.isButtonPressed( Buttons.RIGHT ) ) {
+ camera.position.sub( screenX - lastX, lastY - screenY, 0 );
+ lastX = screenX;
+ lastY = screenY;
+ updateCamera();
+ }
+
+ return super.touchDragged( screenX, screenY, pointer );
+ }
+
+ // updates the camera and stores the stage center for use with MapObject addition to the stage
+ private void updateCamera() {
+
+ camera.update();
+ camera.unproject( vec3.set( 0.5f*Gdx.graphics.getWidth() + camera.position.x / Gdx.graphics.getWidth(),
+ 0.5f*Gdx.graphics.getHeight() + ( Gdx.graphics.getHeight() - camera.position.y ) / Gdx.graphics.getHeight(), 0 ) );
+ worldspaceCenter.set( vec3.x, vec3.y );
+ }
+
+ public Vector2 getCenter() {
+ return worldspaceCenter;
+ }
+
+ // adds an image brush to the stage, packing it into the atlas if not already there
+ public void addImageBrush( MapLayer layer, MapObject object, FileHandle file ) {
+
+ // look for image in atlas, pack if not found
+ AtlasRegion image = imageAtlas.findRegion( file.name() );
+ if ( image == null ) {
+ imagePacker.pack( file.name(), new Pixmap( file ) );
+ imagePacker.updateTextureAtlas( imageAtlas, TextureFilter.Linear, TextureFilter.Linear, true );
+ image = imageAtlas.findRegion( file.name() );
+ }
+
+ // add image to stage
+ ImageBrush brush = new ImageBrush( image, object );
+ brush.setPosition( object.getX(), object.getY() );
+ Group layerGroup = getLayerGroup( layer );
+ if ( layerGroup != null )
+ layerGroup.addActor( brush );
+ }
+
+ private LayerGroup getLayerGroup( MapLayer layer ) {
+
+ SnapshotArray ls = layers.getChildren();
+ for ( int i = 0; i < ls.size; i++ ) {
+ LayerGroup l = (LayerGroup)ls.get( i );
+ if ( layer == l.getLayer() )
+ return l;
+ }
+ return null;
+ }
+
+ @Override
+ public void dispose() {
+
+ super.dispose();
+ imagePacker.dispose();
+ }
+
+ @Override
+ public void onEvent( EventDispatcher dispatcher, Event event ) {
+
+ // model added a layer
+ if ( event instanceof LayerAddedEvent ) {
+ LayerAddedEvent evt = (LayerAddedEvent)event;
+ LayerGroup layer = new LayerGroup( evt.layer );
+ layer.setName( evt.layer.getName() );
+ layers.addActor( layer );
+ return;
+ }
+
+ // model removed a layer
+ if ( event instanceof LayerRemovedEvent ) {
+ LayerRemovedEvent evt = (LayerRemovedEvent)event;
+ LayerGroup layer = getLayerGroup( evt.layer );
+ if ( layer != null )
+ layer.remove();
+ return;
+ }
+
+ // model changed selected layer
+ if ( event instanceof LayerSelectedEvent ) {
+ return;
+ }
+
+ // model hid layer
+ if ( event instanceof LayerHiddenEvent ) {
+ LayerHiddenEvent evt = (LayerHiddenEvent)event;
+ LayerGroup layer = getLayerGroup( evt.layer );
+ if ( layer != null )
+ layer.setVisible( false );
+ return;
+ }
+
+ // model showed layer
+ if ( event instanceof LayerShownEvent ) {
+ LayerShownEvent evt = (LayerShownEvent)event;
+ LayerGroup layer = getLayerGroup( evt.layer );
+ if ( layer != null )
+ layer.setVisible( true );
+ return;
+ }
+
+ // model added an image brush
+ if ( event instanceof ObjectAddedEvent ) {
+ ObjectAddedEvent evt = (ObjectAddedEvent)event;
+ addImageBrush( evt.layer, evt.object, evt.file );
+ }
+ }
+
+ public class LayerGroup extends Group {
+
+ private MapLayer layer;
+ public LayerGroup( MapLayer layer ) {
+
+ this.layer = layer;
+ }
+
+ public MapLayer getLayer() {
+
+ return layer;
+ }
+ }
+
+ public interface StageObject {
+ public MapObject getMapObject();
+ }
+
+ public class ImageBrush extends Image implements StageObject {
+
+ private MapObject object;
+
+ public ImageBrush( AtlasRegion image, MapObject object ) {
+
+ super( image );
+ this.object = object;
+ }
+
+ @Override
+ public MapObject getMapObject() {
+ return object;
+ }
+ }
+}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/MapEditor.java b/maps-editor/src/com/mobidevelop/maps/editor/MapEditor.java
index 875c6b4..a4f41ee 100644
--- a/maps-editor/src/com/mobidevelop/maps/editor/MapEditor.java
+++ b/maps-editor/src/com/mobidevelop/maps/editor/MapEditor.java
@@ -17,31 +17,267 @@
package com.mobidevelop.maps.editor;
import com.badlogic.gdx.ApplicationListener;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.InputMultiplexer;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.GL10;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.scenes.scene2d.Event;
+import com.badlogic.gdx.scenes.scene2d.EventListener;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.SplitPane;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.utils.Align;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.utils.Array;
+import com.badlogic.gdx.utils.Disposable;
+import com.mobidevelop.maps.MapLayer;
+import com.mobidevelop.maps.MapObject;
+import com.mobidevelop.maps.basic.BasicMap;
+import com.mobidevelop.maps.brush.ImageBrushMapObject;
+import com.mobidevelop.maps.editor.models.MapModels.MapModel;
+import com.mobidevelop.maps.editor.ui.FileDialog;
+import com.mobidevelop.maps.editor.ui.ImagePicker;
+import com.mobidevelop.maps.editor.ui.LayerList;
+import com.mobidevelop.maps.editor.ui.SlideWindow;
+import com.mobidevelop.maps.editor.ui.UIEvents;
+import com.mobidevelop.maps.editor.ui.UIEvents.FileEvent;
+import com.mobidevelop.maps.editor.ui.UIEvents.LayerEvent;
+import com.mobidevelop.maps.editor.ui.UIEvents.MapObjectEvent;
+import com.mobidevelop.maps.editor.ui.UIEvents.UIEvent;
-public class MapEditor implements ApplicationListener {
+public class MapEditor implements ApplicationListener, EventListener {
+
+ private SpriteBatch batch;
+
+ private Skin skin;
+ private Stage uiStage;
+ private LevelStage worldViewport;
+
+ private SlideWindow fileWindow;
+ private SlideWindow imageWindow;
+
+ private ImagePicker imagePicker;
+ private LayerList layerList;
+ private FileDialog fileDialog;
+
+ private MapModel mapModel;
+
+ private Array trash;
+
+ private String projectImagePath;
@Override
public void create() {
+
+ float w = Gdx.graphics.getWidth();
+ float h = Gdx.graphics.getHeight();
+
+ batch = new SpriteBatch();
+ skin = new Skin( Gdx.files.internal( "data/uiskin.json" ) );
+
+ fileDialog = new FileDialog( "Set Image Path...", Gdx.files.external( "" ), skin );
+
+ // File Window ********************************************************************************
+
+ final TextButton openProjectButton = new TextButton( "Set Image Path", skin );
+ openProjectButton.addListener( new ClickListener() {
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+
+ fileDialog.editFileName( false );
+ uiStage.addActor( fileDialog );
+ super.clicked( event, x, y );
+ }
+ } );
+ fileWindow = new SlideWindow( skin, Align.top, 10, 200 );
+ fileWindow.add( openProjectButton );
+
+ // Image Window *******************************************************************************
+ // holds the image picker and layer list
+
+ imagePicker = new ImagePicker( skin );
+ layerList = new LayerList( skin );
+ Table pickerTable = new Table();
+ pickerTable.add( imagePicker ).pad( 10 );
+ Table layerTable = new Table();
+ layerTable.add( layerList ).pad( 10 );
+ SplitPane splitPane = new SplitPane( pickerTable, layerTable, true, skin );
+ imageWindow = new SlideWindow( skin, Align.right, 10, 200 );
+ imageWindow.add( splitPane ).expand().fill().pad( 10 );
+
+ // UI Stage ***********************************************************************************
+ // holds the menu overlay, with sliding windows for different tool palettes
+
+ uiStage = new Stage( w, h, true, batch ){
+ @Override
+ public boolean touchDown( int screenX, int screenY, int pointer, int button ) {
+
+ if ( screenY < 20 )
+ fileWindow.showWindow();
+ else if ( screenX > Gdx.graphics.getWidth() - 20 )
+ imageWindow.showWindow();
+
+ return super.touchDown( screenX, screenY, pointer, button );
+ }
+ };
+ uiStage.addListener( this );
+ uiStage.addActor( fileWindow );
+ uiStage.addActor( imageWindow );
+
+ // World Viewport *****************************************************************************
+ // the stage where the map is drawn
+
+ worldViewport = new LevelStage( w, h, batch );
+
+ createNewMap();
+
+ Gdx.input.setInputProcessor( new InputMultiplexer( uiStage, worldViewport ) );
+
+ trash = new Array();
+ trash.add( imagePicker );
+ trash.add( batch );
+ trash.add( skin );
+ trash.add( uiStage );
+ trash.add( worldViewport );
+
+ loadSettings();
+ }
+
+ private void createNewMap() {
+
+ mapModel = new MapModel( new BasicMap() );
+ mapModel.addEventListener( worldViewport );
+ mapModel.addEventListener( layerList );
+
+ // add default layer
+ mapModel.addLayer();
+ mapModel.setCurrentLayer( mapModel.currentLayer() );
}
@Override
public void pause() {
+
+ saveSettings();
}
@Override
public void resume() {
}
-
+
+ private void loadSettings() {
+
+ Settings.load();
+ projectImagePath = Settings.getLastImagePath();
+ if ( projectImagePath != null )
+ imagePicker.loadProjectImages( Gdx.files.external( projectImagePath ) );
+ }
+
+ private void saveSettings() {
+
+ Settings.setLastImagePath( projectImagePath );
+ Settings.save();
+ }
+
@Override
- public void resize(int width, int height) {
+ public void resize( int width, int height ) {
}
@Override
public void render() {
+
+ Gdx.gl.glClearColor( 0, 0, 0, 1 );
+ Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT );
+
+ worldViewport.act();
+ worldViewport.draw();
+
+ uiStage.act();
+ uiStage.draw();
}
@Override
public void dispose() {
+
+ for ( int i = 0; i < trash.size; i++ ) {
+ Disposable d = trash.get( i );
+ if ( d != null )
+ d.dispose();
+ }
+ trash.clear();
}
+ /**
+ * handles events sent by ui components to interact with the model
+ */
+ @Override
+ public boolean handle( Event event ) {
+
+ if ( event instanceof UIEvent ) {
+
+ MapLayer layer;
+ MapObject mapObject;
+ switch ( ((UIEvent)event).type ) {
+ case UIEvents.EV_ADD_LAYER:
+ mapModel.addLayer();
+ break;
+
+ case UIEvents.EV_REMOVE_LAYER:
+ // can't remove last layer
+ if ( mapModel.numLayers() > 1 )
+ mapModel.removeLayer( mapModel.currentLayer() );
+ break;
+
+ case UIEvents.EV_SELECT_LAYER:
+ layer = ((LayerEvent)event).layer;
+ mapModel.setCurrentLayer( layer );
+ break;
+
+ case UIEvents.EV_HIDE_LAYER:
+ layer = ((LayerEvent)event).layer;
+ mapModel.hideLayer( layer );
+ break;
+
+ case UIEvents.EV_SHOW_LAYER:
+ layer = ((LayerEvent)event).layer;
+ mapModel.showLayer( layer );
+ break;
+
+ case UIEvents.EV_ADD_IMAGE:
+ FileEvent eai = (FileEvent)event;
+ FileHandle file = eai.file;
+ layer = mapModel.currentLayer();
+ Vector2 v = worldViewport.getCenter();
+ mapModel.addImageBrush( layer, new ImageBrushMapObject( layer, v.x, v.y, file.name() ), file );
+ break;
+
+ case UIEvents.EV_SELECT_MAP_OBJECT:
+ MapObjectEvent moe = (MapObjectEvent)event;
+ mapObject = moe.object;
+ break;
+
+ case UIEvents.EV_SELECT_IMAGE_PATH:
+ FileEvent esip = (FileEvent)event;
+
+ // ensure folder
+ FileHandle folder = esip.file;
+ if ( !folder.isDirectory() )
+ folder = folder.parent();
+
+ projectImagePath = folder.path();
+ imagePicker.loadProjectImages( esip.file );
+ break;
+
+ default:
+ break;
+ }
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/Settings.java b/maps-editor/src/com/mobidevelop/maps/editor/Settings.java
new file mode 100644
index 0000000..de351f5
--- /dev/null
+++ b/maps-editor/src/com/mobidevelop/maps/editor/Settings.java
@@ -0,0 +1,27 @@
+package com.mobidevelop.maps.editor;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+
+
+public class Settings {
+
+ private static Preferences prefs;
+
+ public static void load() {
+ prefs = Gdx.app.getPreferences( "settings" );
+ }
+
+ public static void save() {
+ if ( prefs != null )
+ prefs.flush();
+ }
+
+ public static String getLastImagePath() {
+ return prefs.getString( "lastImagePath" );
+ }
+
+ public static void setLastImagePath( String imagePath ) {
+ prefs.putString( "lastImagePath", imagePath );
+ }
+}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapCommands.java b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapCommands.java
index e3274cb..16fa567 100644
--- a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapCommands.java
+++ b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapCommands.java
@@ -18,6 +18,7 @@
import com.mobidevelop.maps.Map;
import com.mobidevelop.utils.commands.Command;
+import com.mobidevelop.utils.events.Event;
public class MapCommands {
@@ -50,15 +51,17 @@ public MoveMapCommand(Map map, float newX, float newY) {
}
@Override
- public void execute() {
+ public Event execute() {
map.setX(newX);
- map.setY(newY);
+ map.setY(newY);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
map.setX(oldX);
map.setY(oldY);
+ return null;
}
}
@@ -80,15 +83,17 @@ public ResizeMapCommand(Map map, int newWidth, int newHeight) {
}
@Override
- public void execute() {
+ public Event execute() {
map.setWidth(newWidth);
- map.setHeight(newHeight);
+ map.setHeight(newHeight);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
map.setWidth(oldWidth);
map.setHeight(oldHeight);
+ return null;
}
}
@@ -106,13 +111,15 @@ public RenameMapCommand(Map map, String newName) {
}
@Override
- public void execute() {
+ public Event execute() {
map.setName(newName);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
map.setName(oldName);
+ return null;
}
}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapLayerCommands.java b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapLayerCommands.java
index 9903d2b..6c60b7a 100644
--- a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapLayerCommands.java
+++ b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapLayerCommands.java
@@ -17,7 +17,10 @@
package com.mobidevelop.maps.editor.commands;
import com.mobidevelop.maps.MapLayer;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerHiddenEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerShownEvent;
import com.mobidevelop.utils.commands.Command;
+import com.mobidevelop.utils.events.Event;
public final class MapLayerCommands {
@@ -27,6 +30,10 @@ public static HideLayerCommand hide(MapLayer layer) {
return new HideLayerCommand(layer);
}
+ public static ShowLayerCommand show(MapLayer layer) {
+ return new ShowLayerCommand(layer);
+ }
+
public static MoveLayerCommand move(MapLayer layer, int newX, int newY) {
return new MoveLayerCommand(layer, newX, newY);
}
@@ -39,10 +46,6 @@ public static RenameLayerCommand rename(MapLayer layer, String newName) {
return new RenameLayerCommand(layer, newName);
}
- public static ShowLayerCommand show(MapLayer layer) {
- return new ShowLayerCommand(layer);
- }
-
public static class HideLayerCommand implements Command {
private MapLayer layer;
@@ -52,17 +55,39 @@ public HideLayerCommand(MapLayer layer) {
}
@Override
- public void execute() {
+ public Event execute() {
layer.setVisible(false);
+ return new LayerHiddenEvent( layer );
}
@Override
- public void reverse() {
+ public Event reverse() {
layer.setVisible(true);
+ return new LayerShownEvent( layer );
+ }
+ }
+
+ public static class ShowLayerCommand implements Command {
+
+ private MapLayer layer;
+
+ public ShowLayerCommand(MapLayer layer) {
+ this.layer = layer;
}
+ @Override
+ public Event execute() {
+ layer.setVisible(true);
+ return new LayerShownEvent( layer );
+ }
+
+ @Override
+ public Event reverse() {
+ layer.setVisible(false);
+ return new LayerHiddenEvent( layer );
+ }
}
-
+
public static class MoveLayerCommand implements Command {
private MapLayer layer;
@@ -80,15 +105,17 @@ public MoveLayerCommand(MapLayer layer, int newX, int newY) {
}
@Override
- public void execute() {
+ public Event execute() {
layer.setX(newX);
- layer.setY(newY);
+ layer.setY(newY);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
layer.setX(oldX);
layer.setY(oldY);
+ return null;
}
}
@@ -110,15 +137,17 @@ public ResizeLayerCommand(MapLayer layer, int newWidth, int newHeight) {
}
@Override
- public void execute() {
+ public Event execute() {
layer.setWidth(newWidth);
- layer.setHeight(newHeight);
+ layer.setHeight(newHeight);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
layer.setWidth(oldWidth);
layer.setHeight(oldHeight);
+ return null;
}
}
@@ -136,35 +165,16 @@ public RenameLayerCommand(MapLayer layer, String newName) {
}
@Override
- public void execute() {
+ public Event execute() {
layer.setName(newName);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
layer.setName(oldName);
+ return null;
}
}
-
- public static class ShowLayerCommand implements Command {
-
- private MapLayer layer;
-
- public ShowLayerCommand(MapLayer layer) {
- this.layer = layer;
- }
-
- @Override
- public void execute() {
- layer.setVisible(true);
- }
-
- @Override
- public void reverse() {
- layer.setVisible(false);
- }
-
- }
-
}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapLayersCommands.java b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapLayersCommands.java
index 9b7b94b..89cd8f3 100644
--- a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapLayersCommands.java
+++ b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapLayersCommands.java
@@ -19,14 +19,18 @@
import com.mobidevelop.maps.Map;
import com.mobidevelop.maps.MapLayer;
import com.mobidevelop.maps.MapLayers;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerAddedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerRemovedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerSwappedEvent;
import com.mobidevelop.utils.commands.Command;
+import com.mobidevelop.utils.events.Event;
final public class MapLayersCommands {
private MapLayersCommands() { }
- public static AddLayerCommand add(Map map, MapLayer layer) {
- return new AddLayerCommand(map, layer);
+ public static AddLayerCommand add(Map map, String layerName) {
+ return new AddLayerCommand(map, layerName);
}
public static InsertLayerCommand insert(Map map, int index, MapLayer layer) {
@@ -43,23 +47,26 @@ public static SwapLayersCommand swap(Map map, MapLayer layer1, MapLayer layer2)
public static class AddLayerCommand implements Command {
private Map map;
+ private String layerName;
private MapLayer layer;
- public AddLayerCommand(Map map, MapLayer layer) {
+ public AddLayerCommand(Map map, String name) {
this.map = map;
- this.layer = layer;
+ this.layerName = name;
}
@Override
- public void execute() {
- map.getLayers().addLayer(layer);
+ public Event execute() {
+ layer = map.createLayer( layerName );
+ map.getLayers().addLayer( layer );
+ return new LayerAddedEvent( layer );
}
@Override
- public void reverse() {
- map.getLayers().removeLayer(layer);
+ public Event reverse() {
+ map.getLayers().removeLayer( layer );
+ return new LayerRemovedEvent( layer );
}
-
}
public static class InsertLayerCommand implements Command {
@@ -76,13 +83,15 @@ public InsertLayerCommand(Map map, int index, MapLayer layer) {
}
@Override
- public void execute() {
+ public Event execute() {
map.getLayers().addLayer(index, layer);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
map.getLayers().removeLayer(layer);
+ return null;
}
}
@@ -98,17 +107,20 @@ public RemoveLayerCommand(Map map, MapLayer layer) {
this.map = map;
this.layer = layer;
}
-
+
@Override
- public void execute() {
+ public Event execute() {
MapLayers layers = map.getLayers();
- index = layers.getIndex(layer);
- layers.removeLayer(index);
+ index = layers.getIndex( layer );
+ layers.removeLayer( layer );
+ return new LayerRemovedEvent( layer );
}
+
@Override
- public void reverse() {
+ public Event reverse() {
MapLayers layers = map.getLayers();
- layers.addLayer(index, layer);
+ layers.addLayer( index, layer );
+ return new LayerAddedEvent( layer );
}
}
@@ -130,15 +142,17 @@ public SwapLayersCommand(Map map, MapLayer layer1, MapLayer layer2) {
this.layer1 = layer1;
this.layer2 = layer2;
}
-
+
@Override
- public void execute() {
- map.getLayers().swapLayers(layer1, layer2);
+ public Event execute() {
+ map.getLayers().swapLayers( layer1, layer2 );
+ return new LayerSwappedEvent( layer1, layer2 );
}
@Override
- public void reverse() {
+ public Event reverse() {
map.getLayers().swapLayers(layer1, layer2);
+ return new LayerSwappedEvent( layer1, layer2 );
}
}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapObjectCommands.java b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapObjectCommands.java
index 0e74cd6..25c25dc 100644
--- a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapObjectCommands.java
+++ b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapObjectCommands.java
@@ -18,6 +18,7 @@
import com.mobidevelop.maps.MapObject;
import com.mobidevelop.utils.commands.Command;
+import com.mobidevelop.utils.events.Event;
public final class MapObjectCommands {
@@ -27,11 +28,11 @@ public static HideObjectCommand hide(MapObject object) {
return new HideObjectCommand(object);
}
- public static MoveObjectCommand move(MapObject object, int newX, int newY) {
+ public static MoveObjectCommand move(MapObject object, float newX, float newY) {
return new MoveObjectCommand(object, newX, newY);
}
- public static ResizeObjectCommand resize(MapObject object, int newWidth, int newHeight) {
+ public static ResizeObjectCommand resize(MapObject object, float newWidth, float newHeight) {
return new ResizeObjectCommand(object, newWidth, newHeight);
}
@@ -52,13 +53,15 @@ public HideObjectCommand(MapObject object) {
}
@Override
- public void execute() {
+ public Event execute() {
object.setVisible(false);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
object.setVisible(true);
+ return null;
}
}
@@ -71,7 +74,7 @@ public static class MoveObjectCommand implements Command {
private float newX;
private float newY;
- public MoveObjectCommand(MapObject object, int newX, int newY) {
+ public MoveObjectCommand(MapObject object, float newX, float newY) {
this.object = object;
this.oldX = object.getX();
this.oldY = object.getY();
@@ -80,15 +83,17 @@ public MoveObjectCommand(MapObject object, int newX, int newY) {
}
@Override
- public void execute() {
+ public Event execute() {
object.setX(newX);
- object.setY(newY);
+ object.setY(newY);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
object.setX(oldX);
object.setY(oldY);
+ return null;
}
}
@@ -101,7 +106,7 @@ public static class ResizeObjectCommand implements Command {
private float newWidth;
private float newHeight;
- public ResizeObjectCommand(MapObject object, int newWidth, int newHeight) {
+ public ResizeObjectCommand(MapObject object, float newWidth, float newHeight) {
this.object = object;
this.oldWidth = object.getWidth();
this.oldHeight = object.getHeight();
@@ -110,15 +115,17 @@ public ResizeObjectCommand(MapObject object, int newWidth, int newHeight) {
}
@Override
- public void execute() {
+ public Event execute() {
object.setWidth(newWidth);
object.setHeight(newHeight);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
object.setWidth(oldWidth);
object.setHeight(oldHeight);
+ return null;
}
}
@@ -136,13 +143,15 @@ public RenameObjectCommand(MapObject object, String newName) {
}
@Override
- public void execute() {
+ public Event execute() {
object.setName(newName);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
object.setName(oldName);
+ return null;
}
}
@@ -156,13 +165,15 @@ public ShowObjectCommand(MapObject object) {
}
@Override
- public void execute() {
+ public Event execute() {
object.setVisible(true);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
object.setVisible(false);
+ return null;
}
}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapObjectsCommands.java b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapObjectsCommands.java
index bbb70a3..fe1b645 100644
--- a/maps-editor/src/com/mobidevelop/maps/editor/commands/MapObjectsCommands.java
+++ b/maps-editor/src/com/mobidevelop/maps/editor/commands/MapObjectsCommands.java
@@ -16,25 +16,30 @@
package com.mobidevelop.maps.editor.commands;
+import com.badlogic.gdx.files.FileHandle;
import com.mobidevelop.maps.MapLayer;
import com.mobidevelop.maps.MapObject;
import com.mobidevelop.maps.MapObjects;
+import com.mobidevelop.maps.editor.models.MapModels.MapObjectsModel.ObjectAddedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapObjectsModel.ObjectRemovedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapObjectsModel.ObjectSwappedEvent;
import com.mobidevelop.utils.commands.Command;
+import com.mobidevelop.utils.events.Event;
public final class MapObjectsCommands {
private MapObjectsCommands() { }
- public static AddObjectCommand add(MapLayer layer, MapObject object) {
- return new AddObjectCommand(layer, object);
+ public static AddObjectCommand add(MapLayer layer, MapObject object, FileHandle file) {
+ return new AddObjectCommand(layer, object, file);
}
public static InsertObjectCommand insert(MapLayer layer, int index, MapObject object) {
return new InsertObjectCommand(layer, index, object);
}
- public static RemoveObjectCommand remove(MapLayer layer, MapObject object) {
- return new RemoveObjectCommand(layer, object);
+ public static RemoveObjectCommand remove(MapLayer layer, MapObject object, FileHandle file) {
+ return new RemoveObjectCommand(layer, object, file);
}
public static SwapObjectsCommand swap(MapLayer layer, MapObject object1, MapObject object2) {
@@ -45,20 +50,24 @@ public static class AddObjectCommand implements Command {
private MapLayer layer;
private MapObject object;
+ private FileHandle file;
- public AddObjectCommand(MapLayer layer, MapObject object) {
+ public AddObjectCommand(MapLayer layer, MapObject object, FileHandle file) {
this.layer = layer;
this.object = object;
+ this.file = file;
}
@Override
- public void execute() {
+ public Event execute() {
layer.getObjects().addObject(object);
+ return new ObjectAddedEvent( layer, object, file );
}
@Override
- public void reverse() {
+ public Event reverse() {
layer.getObjects().removeObject(object);
+ return new ObjectRemovedEvent( layer, object );
}
}
@@ -77,13 +86,15 @@ public InsertObjectCommand(MapLayer layer, int index, MapObject object) {
}
@Override
- public void execute() {
+ public Event execute() {
layer.getObjects().addObject(index, object);
+ return null;
}
@Override
- public void reverse() {
+ public Event reverse() {
layer.getObjects().removeObject(object);
+ return null;
}
}
@@ -91,26 +102,29 @@ public void reverse() {
public static class RemoveObjectCommand implements Command {
private MapLayer layer;
-
private MapObject object;
+ private FileHandle file;
private int index;
- public RemoveObjectCommand(MapLayer layer, MapObject object) {
+ public RemoveObjectCommand(MapLayer layer, MapObject object, FileHandle file ) {
this.layer = layer;
this.object = object;
+ this.file = file;
}
@Override
- public void execute() {
+ public Event execute() {
MapObjects objects = layer.getObjects();
index = objects.getIndex(object);
objects.removeObject(index);
+ return new ObjectRemovedEvent( layer, object );
}
@Override
- public void reverse() {
+ public Event reverse() {
MapObjects objects = layer.getObjects();
objects.addObject(index, object);
+ return new ObjectAddedEvent( layer, object, file );
}
}
@@ -135,14 +149,16 @@ public SwapObjectsCommand(MapLayer layer, MapObject object1, MapObject object2)
}
@Override
- public void execute() {
+ public Event execute() {
layer.getObjects().swapObjects(object1, object2);
+ return new ObjectSwappedEvent( object1, object2 );
}
@Override
- public void reverse() {
+ public Event reverse() {
layer.getObjects().swapObjects(object1, object2);
+ return new ObjectSwappedEvent( object1, object2 );
}
-
+
}
}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/models/MapModels.java b/maps-editor/src/com/mobidevelop/maps/editor/models/MapModels.java
index ffad80f..44abc12 100644
--- a/maps-editor/src/com/mobidevelop/maps/editor/models/MapModels.java
+++ b/maps-editor/src/com/mobidevelop/maps/editor/models/MapModels.java
@@ -19,8 +19,13 @@
import java.util.ArrayList;
import java.util.List;
+import com.badlogic.gdx.files.FileHandle;
import com.mobidevelop.maps.Map;
import com.mobidevelop.maps.MapLayer;
+import com.mobidevelop.maps.MapObject;
+import com.mobidevelop.maps.editor.commands.MapLayerCommands;
+import com.mobidevelop.maps.editor.commands.MapLayersCommands;
+import com.mobidevelop.maps.editor.commands.MapObjectsCommands;
import com.mobidevelop.utils.commands.CommandManager;
import com.mobidevelop.utils.events.Event;
import com.mobidevelop.utils.events.EventDispatcher;
@@ -87,8 +92,20 @@ public static class MapModel extends Model {
public MapModel(Map map) {
this.map = map;
+ commands = new CommandManager( this );
+ layersModel = new MapLayersModel( this );
+ objectsModel = new MapObjectsModel( this );
}
+
+ @Override
+ public void addEventListener( EventListener listener ) {
+ super.addEventListener( listener );
+
+ layersModel.addEventListener( listener );
+ objectsModel.addEventListener( listener );
+ }
+
public String getFile() {
return file;
}
@@ -103,43 +120,174 @@ public boolean save() {
public boolean saveAs(String file) {
return false;
}
-
- }
+
+ public void addLayer() {
+ layersModel.addLayer();
+ }
+ public void removeLayer( MapLayer layer ) {
+ // deleting current layer, set layer to next nearest
+ if ( layersModel.getCurrentLayer() == layer ) {
+ int index = map.getLayers().getIndex( layer ) - 1;
+ if ( index < 0 )
+ index = 1;
+ MapLayer nextLayer = map.getLayers().getLayer( index );
+ layersModel.setCurrentLayer( nextLayer );
+ }
+ layersModel.removeLayer( layer );
+ }
+
+ public MapLayer currentLayer() {
+ return layersModel.getCurrentLayer();
+ }
+
+ public int numLayers() {
+
+ return map.getLayers().getCount();
+ }
+
+ public void addImageBrush( MapLayer layer, MapObject object, FileHandle file ) {
+
+ objectsModel.add( layer, object, file );
+ }
+
+ public void setCurrentLayer( MapLayer layer ) {
+
+ layersModel.setCurrentLayer( layer );
+ }
+
+ public void showLayer( MapLayer layer ) {
+
+ layersModel.hideLayer( layer );
+ }
+
+ public void hideLayer( MapLayer layer ) {
+
+ layersModel.showLayer( layer );
+ }
+ }
+
public static class MapLayersModel extends Model {
private MapModel model;
+ private int currentLayer = 0;
+ private int lastCreatedLayer = 0;
- public MapLayersModel() {
-
+ public MapLayersModel(MapModel mapModel) {
+
+ setMapModel( mapModel );
}
+ public void setCurrentLayer( MapLayer layer ) {
+
+ currentLayer = model.map.getLayers().getIndex( layer );
+ dispatchEvent( new LayerSelectedEvent( layer ) );
+ }
+
+ public MapLayer getCurrentLayer() {
+
+ return this.model.map.getLayers().getLayer( currentLayer );
+ }
+
public void setMapModel(MapModel model) {
this.model = model;
}
-
- public void addLayer(MapLayer layer) {
- this.model.map.getLayers().addLayer(layer);
- this.dispatchEvent(new LayerAddedEvent());
+
+ public void addLayer() {
+ model.commands.execute( MapLayersCommands.add( model.map, "Layer " + ++lastCreatedLayer ) );
}
public void removeLayer(MapLayer layer) {
- this.model.map.getLayers().removeLayer(layer);
- this.dispatchEvent(new LayerRemovedEvent());
+ model.commands.execute( MapLayersCommands.remove( model.map, layer ) );
}
-
- public static class LayerAddedEvent extends Event {
-
+
+ public void hideLayer( MapLayer layer ) {
+ model.commands.execute( MapLayerCommands.hide( layer ) );
}
- public static class LayerRemovedEvent extends Event {
-
+
+ public void showLayer( MapLayer layer ) {
+ model.commands.execute( MapLayerCommands.show( layer ) );
+ }
+
+ public static class LayerEvent extends Event {
+ public MapLayer layer;
+ public LayerEvent( MapLayer layer ) {
+ this.layer = layer;
+ }
+ }
+ public static class LayerAddedEvent extends LayerEvent {
+ public LayerAddedEvent( MapLayer layer ) { super( layer ); }
+ }
+ public static class LayerRemovedEvent extends LayerEvent {
+ public LayerRemovedEvent( MapLayer layer ) { super( layer ); }
+ }
+ public static class LayerSelectedEvent extends LayerEvent {
+ public LayerSelectedEvent( MapLayer layer ) { super( layer ); }
+ }
+ public static class LayerSwappedEvent extends LayerEvent {
+ public MapLayer layer2;
+ public LayerSwappedEvent( MapLayer layer, MapLayer layer2 ) {
+ super( layer );
+ this.layer2 = layer2;
+ }
+ }
+ public static class LayerHiddenEvent extends LayerEvent {
+ public LayerHiddenEvent( MapLayer layer ) { super( layer ); }
+ }
+ public static class LayerShownEvent extends LayerEvent {
+ public LayerShownEvent( MapLayer layer ) { super( layer ); }
}
}
-
+
public static class MapObjectsModel extends Model {
- private MapLayer model;
-
+ private MapModel model;
+
+ public MapObjectsModel( MapModel mapModel ) {
+
+ setMapModel( mapModel );
+ }
+
+ public void setMapModel(MapModel model) {
+ this.model = model;
+ }
+
+ public void add( MapLayer layer, MapObject mapObject, FileHandle file ) {
+
+ model.commands.execute( MapObjectsCommands.add( layer, mapObject, file ) );
+ }
+
+ public static class ObjectAddedEvent extends Event {
+
+ public MapLayer layer;
+ public MapObject object;
+ public FileHandle file;
+ public ObjectAddedEvent( MapLayer layer, MapObject object, FileHandle file ) {
+
+ this.layer = layer;
+ this.object = object;
+ this.file = file;
+ }
+ }
+ public static class ObjectRemovedEvent extends Event {
+
+ public MapLayer layer;
+ public MapObject object;
+ public ObjectRemovedEvent( MapLayer layer, MapObject object ) {
+
+ this.layer = layer;
+ this.object = object;
+ }
+ }
+ public static class ObjectSwappedEvent extends Event {
+
+ public MapObject object1;
+ public MapObject object2;
+ public ObjectSwappedEvent( MapObject object1, MapObject object2 ) {
+
+ this.object1 = object1;
+ this.object2 = object2;
+ }
+ }
}
-
}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/ui/FileDialog.java b/maps-editor/src/com/mobidevelop/maps/editor/ui/FileDialog.java
new file mode 100644
index 0000000..817efb9
--- /dev/null
+++ b/maps-editor/src/com/mobidevelop/maps/editor/ui/FileDialog.java
@@ -0,0 +1,108 @@
+package com.mobidevelop.maps.editor.ui;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.ui.List;
+import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.ui.TextField;
+import com.badlogic.gdx.scenes.scene2d.ui.Window;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+
+
+public class FileDialog extends Window {
+
+ List fileList;
+ TextField fileName;
+ private String lastFolder;
+
+ public FileDialog( String title, FileHandle initialFolder, Skin skin ) {
+
+ super( title, skin );
+
+ setModal( true );
+ setFillParent( true );
+
+ lastFolder = initialFolder.path();
+ fileList = new List( initialFolder.list(), skin );
+ fileList.addListener( new ClickListener() {
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+
+ String path = lastFolder + "/" + Gdx.files.external( fileList.getSelection() ).name();
+ FileHandle file = Gdx.files.external( path );
+ if ( file.isDirectory() ) {
+ lastFolder = path;
+ loadFileList( file.list() );
+ } else {
+ fileName.setText( file.name() );
+ }
+ }
+ } );
+ final ScrollPane listScroll = new ScrollPane( fileList );
+
+ final TextButton upButton = new TextButton( "Up", skin );
+ upButton.addListener( new ClickListener() {
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+ lastFolder = Gdx.files.external( lastFolder ).parent().name();
+ loadFileList( Gdx.files.external( lastFolder ).list() );
+ }
+ });
+
+ final TextButton okButton = new TextButton( "OK", skin );
+ okButton.addListener( new ClickListener() {
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+
+ String path = lastFolder + "/" + fileList.getSelection();
+ FileHandle file = Gdx.files.external( path );
+// if ( file.isDirectory() ) {
+// loadFileList( file.list() );
+// } else {
+ fire( UIEvents.selectImagePath( file ) );
+ remove();
+// }
+ }
+ });
+ final TextButton cancelButton = new TextButton( "Cancel", skin );
+ cancelButton.addListener( new ClickListener() {
+ public void clicked( InputEvent event, float x, float y ) {
+ remove();
+ }
+ } );
+
+ fileName = new TextField( "", skin );
+
+ Table table = new Table( skin );
+ table.defaults().fill().padTop( 10 ).padBottom( 10 );
+ table.row();
+ table.add( upButton ).colspan( 2 );
+ table.row();
+ table.add( listScroll ).expand().colspan( 2 );
+ table.row();
+ table.add( fileName );
+ table.row();
+ table.add( okButton );
+ table.add( cancelButton );
+
+ add( table );
+ }
+
+ public void editFileName( boolean enable ) {
+
+ fileName.setDisabled( !enable );
+ }
+
+ private void loadFileList( FileHandle[] list ) {
+
+ String[] items = new String[list.length];
+ for ( int i = 0; i < items.length; i++ ) {
+ items[i] = list[i].name();
+ }
+ fileList.setItems( items );
+ }
+}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/ui/ImagePicker.java b/maps-editor/src/com/mobidevelop/maps/editor/ui/ImagePicker.java
new file mode 100644
index 0000000..2b8434c
--- /dev/null
+++ b/maps-editor/src/com/mobidevelop/maps/editor/ui/ImagePicker.java
@@ -0,0 +1,115 @@
+package com.mobidevelop.maps.editor.ui;
+
+import java.util.HashMap;
+
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Pixmap.Format;
+import com.badlogic.gdx.graphics.Texture.TextureFilter;
+import com.badlogic.gdx.graphics.g2d.PixmapPacker;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.utils.Array;
+import com.badlogic.gdx.utils.Disposable;
+
+
+public class ImagePicker extends Table implements Disposable {
+
+ private PixmapPacker thumbPacker = null;
+ private TextureAtlas thumbImageAtlas;
+ private HashMap projectImages;
+
+ private Table thumbTable;
+
+ public ImagePicker( final Skin skin ) {
+
+ thumbImageAtlas = new TextureAtlas();
+ projectImages = new HashMap();
+
+ // thumbnails sit in a table within a scroll pane
+ thumbTable = new Table();
+ thumbTable.row();
+ thumbTable.add( new Label( "No images loaded", skin ) );
+ final ScrollPane thumbScroll = new ScrollPane( thumbTable );
+
+ // add click listener to send event for new image to stage
+ thumbScroll.addListener( new ClickListener() {
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+
+ Actor actor = thumbScroll.hit( x, y, false );
+ if ( actor != null ) {
+ FileHandle file = projectImages.get( actor.getName() );
+ if ( file != null )
+ fire( UIEvents.addImageEvent( file ) );
+ }
+ super.clicked( event, x, y );
+ }
+ } );
+
+ add( thumbScroll );
+ }
+
+ /**
+ * creates a 64x64 thumbnail from the given file (should be an image file)
+ * @param img
+ */
+ private void packImageThumb( FileHandle img ) {
+
+ projectImages.put( img.name(), img );
+ Pixmap fullImage = new Pixmap( img );
+ Pixmap thumb = new Pixmap( 64, 64, Format.RGB565 );
+ thumb.drawPixmap( fullImage, 0, 0, fullImage.getWidth(), fullImage.getHeight(), 0, 0, thumb.getWidth(), thumb.getHeight() );
+ thumbPacker.pack( img.name(), thumb );
+ }
+
+ /**
+ * loads images from the project image folder into thumbnails on the image window
+ * @param file the folder to load images from
+ */
+ public void loadProjectImages( FileHandle folder ) {
+
+ // reset thumbs
+ if ( thumbPacker != null )
+ thumbPacker.dispose();
+ thumbPacker = new PixmapPacker( 1024, 1024, Format.RGBA8888, 2, false );
+ projectImages.clear();
+
+ // get image thumbs and pack into atlas
+ FileHandle[] list = folder.list();
+ for ( int i = 0; i < list.length; i++ ) {
+ FileHandle img = list[i];
+ String ext = img.extension().toLowerCase();
+ if ( ext.contentEquals( "png" ) || ext.contentEquals( "jpg" ) ) {
+ packImageThumb( img );
+ }
+ }
+ thumbPacker.updateTextureAtlas( thumbImageAtlas, TextureFilter.Linear, TextureFilter.Linear, true );
+
+ // load thumbs into image listbox
+ Array regions = thumbImageAtlas.getRegions();
+ thumbTable.clear();
+ for ( int i = 0; i < regions.size; i++ ) {
+ AtlasRegion region = regions.get( i );
+ Image img = new Image( region );
+ img.setName( region.name );
+ thumbTable.row();
+ thumbTable.add( img );
+ }
+ }
+
+ @Override
+ public void dispose() {
+
+ if ( thumbPacker != null )
+ thumbPacker.dispose();
+ }
+}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/ui/LayerList.java b/maps-editor/src/com/mobidevelop/maps/editor/ui/LayerList.java
new file mode 100644
index 0000000..5a028ce
--- /dev/null
+++ b/maps-editor/src/com/mobidevelop/maps/editor/ui/LayerList.java
@@ -0,0 +1,181 @@
+package com.mobidevelop.maps.editor.ui;
+
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.Touchable;
+import com.badlogic.gdx.scenes.scene2d.ui.Button;
+import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.utils.SnapshotArray;
+import com.mobidevelop.maps.MapLayer;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerAddedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerRemovedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerSelectedEvent;
+import com.mobidevelop.maps.editor.models.MapModels.MapLayersModel.LayerSwappedEvent;
+import com.mobidevelop.utils.events.Event;
+import com.mobidevelop.utils.events.EventDispatcher;
+import com.mobidevelop.utils.events.EventListener;
+
+
+public class LayerList extends Table implements EventListener {
+
+ private Skin skin;
+ private VerticalGroup layers;
+ private Label lastSelected;
+
+ public LayerList( final Skin skin ) {
+
+ this.skin = skin;
+
+ // rich list box for the layers, just a vertical group of LayerActors in a ScrollPane
+ layers = new VerticalGroup();
+ layers.addListener( new ClickListener() {
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+ Actor actor = layers.hit( x, y, true );
+ if ( actor instanceof Label ) {
+ // hacky way to get the layer
+ Label lbl = (Label) actor;
+ fire( UIEvents.selectLayer( ((LayerListActor)lbl.getParent()).getLayer() ) );
+ }
+ }
+ } );
+ final ScrollPane layerScroll = new ScrollPane( layers );
+ layerScroll.setOverscroll( false, true );
+
+ // controls for add/removing layers
+ final TextButton addLayerButton = new TextButton( "New Layer", skin );
+ addLayerButton.addListener( new ClickListener() {
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+ fire( UIEvents.addLayerEvent() );
+ }
+ });
+ final TextButton removeLayerButton = new TextButton( "Remove Layer", skin );
+ removeLayerButton.addListener( new ClickListener() {
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+ fire( UIEvents.removeLayerEvent() );
+ }
+ });
+
+ defaults().pad( 10 );
+ row();
+ add( layerScroll ).colspan( 2 );
+ row();
+ add( addLayerButton );
+ add( removeLayerButton );
+ }
+
+ @Override
+ public void onEvent( EventDispatcher dispatcher, Event event ) {
+
+ // model added layer
+ if ( event instanceof LayerAddedEvent ) {
+ MapLayer layer = ((LayerAddedEvent)event).layer;
+ LayerListActor actor = new LayerListActor( layer, skin );
+ layers.addActorAt( layer.getMap().getLayers().getIndex( layer ), actor );
+ return;
+ }
+
+ // model removed layer
+ if ( event instanceof LayerRemovedEvent ) {
+ Actor actor = getLayerActor( ((LayerRemovedEvent)event).layer );
+ if ( actor != null )
+ actor.remove();
+ return;
+ }
+
+ // model changed selected layer
+ if ( event instanceof LayerSelectedEvent ) {
+ selectLayer( ((LayerSelectedEvent)event).layer );
+ }
+
+ // model swapped layers
+ if ( event instanceof LayerSwappedEvent ) {
+ LayerSwappedEvent evt = (LayerSwappedEvent)event;
+ Actor actor1 = getLayerActor( evt.layer );
+ Actor actor2 = getLayerActor( evt.layer2 );
+ if ( actor1 != null && actor2 != null )
+ layers.swapActor( actor1, actor2 );
+ return;
+ }
+ }
+
+ public LayerListActor getLayerActor( MapLayer layer ) {
+
+ SnapshotArray ls = layers.getChildren();
+ for ( int i = 0; i < ls.size; i++ ) {
+ LayerListActor l = (LayerListActor)ls.get( i );
+ if ( layer == l.getLayer() )
+ return l;
+ }
+ return null;
+ }
+
+ public void selectLayer( MapLayer layer ) {
+
+ if ( lastSelected != null ) {
+ lastSelected.setStyle( skin.get( "default", LabelStyle.class ) );
+ }
+ lastSelected = getLayerActor( layer ).getLabel();
+ lastSelected.setStyle( skin.get( "selected", LabelStyle.class ) );
+ }
+
+ // LayerListActor will represent a layer in the listbox, with controls to handle locking/visibility, etc.
+ public class LayerListActor extends Table {
+
+ private MapLayer layer;
+ private Label label;
+
+ public LayerListActor( MapLayer layer, Skin skin ) {
+
+ this.layer = layer;
+
+ setTouchable( Touchable.childrenOnly );
+ setName( layer.getName() );
+ label = new Label( getName(), skin );
+ label.setTouchable( Touchable.enabled );
+
+ final CheckBox showHideButton = new CheckBox( "", skin );
+ showHideButton.addListener( new ClickShowHideListener( showHideButton, layer ) );
+ showHideButton.setChecked( true );
+
+ row();
+ add( showHideButton );
+ add( label );
+ }
+
+ public Label getLabel() {
+ return label;
+ }
+
+ public MapLayer getLayer() {
+ return layer;
+ }
+ }
+
+ public class ClickShowHideListener extends ClickListener {
+ private Button button;
+ private MapLayer layer;
+ public ClickShowHideListener( Button button, MapLayer layer ) {
+ this.button = button;
+ this.layer = layer;
+ }
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+ if ( button.isChecked() )
+ fire( UIEvents.hideLayer( layer ) );
+ else
+ fire( UIEvents.showLayer( layer ) );
+ super.clicked( event, x, y );
+ }
+ }
+}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/ui/SlideWindow.java b/maps-editor/src/com/mobidevelop/maps/editor/ui/SlideWindow.java
new file mode 100644
index 0000000..3ab1684
--- /dev/null
+++ b/maps-editor/src/com/mobidevelop/maps/editor/ui/SlideWindow.java
@@ -0,0 +1,148 @@
+package com.mobidevelop.maps.editor.ui;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.math.Interpolation;
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.Touchable;
+import com.badlogic.gdx.scenes.scene2d.actions.Actions;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.ui.Window;
+import com.badlogic.gdx.scenes.scene2d.utils.Align;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+
+
+public class SlideWindow extends Window {
+
+ private Vector2 startPos = new Vector2();
+ private Vector2 goalPos = new Vector2();
+
+ /**
+ * creates a window that slides in from screen edge determined by origin (using {@link com.badlogic.gdx.scenes.scene2d.utils.Align Align})
+ * @param skin skin file to use
+ * @param origin which edge of the screen to slide from (see {@link com.badlogic.gdx.scenes.scene2d.utils.Align Align})
+ * @param margin amount of empty space to leave around window
+ */
+ public SlideWindow( Skin skin, int origin, float margin ) {
+
+ this( skin, origin, margin, 0 );
+ }
+
+ /**
+ * creates a window that slides in from screen edge determined by origin (using {@link com.badlogic.gdx.scenes.scene2d.utils.Align Align})
+ * @param skin skin file to use
+ * @param origin which edge of the screen to slide from (see {@link com.badlogic.gdx.scenes.scene2d.utils.Align Align})
+ * @param margin amount of empty space to leave around window
+ * @param lip size of window along sliding axis (0 = fullscreen)
+ */
+ public SlideWindow( Skin skin, int origin, float margin, float lip ) {
+
+ super( "", skin );
+
+ float w = Gdx.graphics.getWidth();
+ float h = Gdx.graphics.getHeight();
+ float ww = w - 2*margin;
+ float wh = h - 2*margin;
+
+ // setup window with desired dimensions to slide in from edge of screen determined by origin
+ if ( ( origin & Align.left ) != 0 ) {
+
+ ww = lip > 0 ? lip : ww;
+ setupWindow( skin, ww, wh, -( ww + 2*margin ), margin, margin, margin );
+
+ } else if ( ( origin & Align.right ) != 0 ) {
+
+ ww = lip > 0 ? lip : ww;
+ setupWindow( skin, ww, wh, w + 2*margin, margin, w - ( ww + margin ), margin );
+
+ } else if ( ( origin & Align.top ) != 0 ) {
+
+ wh = lip > 0 ? lip : wh;
+ setupWindow( skin, ww, wh, margin, h + 2*margin, margin, h - ( wh + margin ) );
+
+ } else if ( ( origin & Align.bottom ) != 0 ) {
+
+ wh = lip > 0 ? lip : wh;
+ setupWindow( skin, ww, wh, margin, -( wh + 2*margin ), margin, margin );
+
+ // default center
+ } else {
+
+ setupWindow( skin, ww, wh, margin, margin, margin, margin );
+ }
+ }
+
+ /**
+ * creates a slide window with all properties explicitly defined
+ * @param skin
+ * @param windowWidth
+ * @param windowHeight
+ * @param startPosX
+ * @param startPosY
+ * @param goalPosX
+ * @param goalPosY
+ */
+ public SlideWindow( Skin skin, float windowWidth, float windowHeight, float startPosX, float startPosY, float goalPosX, float goalPosY ) {
+
+ super( "", skin );
+
+ setupWindow( skin, windowWidth, windowHeight, startPosX, startPosY, goalPosX, goalPosY );
+ }
+
+ private void setupWindow( Skin skin, float width, float height, float startPosX, float startPosY, float goalPosX, float goalPosY ) {
+
+ startPos.set( startPosX, startPosY );
+ goalPos.set( goalPosX, goalPosY );
+
+// // remove listener which pushes window to front when clicked
+// removeCaptureListener( getCaptureListeners().get( 0 ) );
+
+ // kill click events on the window
+ addListener( new ClickListener() {
+ @Override
+ public boolean touchDown( InputEvent event, float x, float y, int pointer, int button ) {
+ super.touchDown( event, x, y, pointer, button );
+ return true;
+ }
+ } );
+ setTouchable( Touchable.enabled );
+ setBackground( skin.getDrawable( "default-round" ) );
+ setKeepWithinStage( false );
+
+ // add a close button
+ TextButton dismisser = new TextButton( "X", skin );
+ dismisser.addListener( new ClickListener() {
+ @Override
+ public void clicked( InputEvent event, float x, float y ) {
+ hideWindow();
+ }
+ });
+ row();
+ add( dismisser ).align( Align.right );
+
+ setSize( width, height );
+ setPosition( startPos.x, startPos.y );
+ }
+
+ /**
+ * show the window with a slide and fade-in
+ */
+ public void showWindow() {
+
+ clearActions();
+ setPosition( startPos.x, startPos.y );
+ setColor( 1, 1, 1, 0 );
+ addAction( Actions.parallel( Actions.moveTo( goalPos.x, goalPos.y, 0.3f, Interpolation.swingOut ), Actions.fadeIn( 0.3f ) ) );
+ }
+
+ /**
+ * hide the window with a slide and fade-out
+ */
+ public void hideWindow() {
+
+ clearActions();
+ setPosition( goalPos.x, goalPos.y );
+ addAction( Actions.parallel( Actions.moveTo( startPos.x, startPos.y, 0.3f ), Actions.fadeOut( 0.3f, Interpolation.exp10Out ) ) );
+ }
+}
diff --git a/maps-editor/src/com/mobidevelop/maps/editor/ui/UIEvents.java b/maps-editor/src/com/mobidevelop/maps/editor/ui/UIEvents.java
new file mode 100644
index 0000000..73d94d6
--- /dev/null
+++ b/maps-editor/src/com/mobidevelop/maps/editor/ui/UIEvents.java
@@ -0,0 +1,66 @@
+package com.mobidevelop.maps.editor.ui;
+
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.scenes.scene2d.Event;
+import com.mobidevelop.maps.MapLayer;
+import com.mobidevelop.maps.MapObject;
+
+
+public class UIEvents {
+
+ public static final int EV_ADD_LAYER = 1;
+ public static final int EV_REMOVE_LAYER = 2;
+ public static final int EV_SELECT_LAYER = 3;
+ public static final int EV_HIDE_LAYER = 4;
+ public static final int EV_SHOW_LAYER = 5;
+ public static final int EV_ADD_IMAGE = 6;
+ public static final int EV_SELECT_MAP_OBJECT = 7;
+ public static final int EV_SELECT_IMAGE_PATH = 8;
+
+ /**
+ * UIEvents are events the scene2d.ui uses to interact with the model.
+ * They are sent by different ui components and handled by the main uiStage, where the model interaction occurs.
+ * The model has it's own events which each ui component responds to as needed.
+ * @author Josh
+ *
+ */
+ public static class UIEvent extends Event {
+ public int type;
+ public UIEvent( int type ) {
+ this.type = type;
+ }
+ }
+
+ public static class LayerEvent extends UIEvent {
+ public MapLayer layer;
+ public LayerEvent( int type, MapLayer layer ) {
+ super( type );
+ this.layer = layer;
+ }
+ }
+
+ public static class MapObjectEvent extends UIEvent {
+ public MapObject object;
+ public MapObjectEvent( int type, MapObject object ) {
+ super( type );
+ this.object = object;
+ }
+ }
+
+ public static class FileEvent extends UIEvent {
+ public FileHandle file;
+ public FileEvent( int type, FileHandle file ) {
+ super( type );
+ this.file = file;
+ }
+ }
+
+ public static UIEvent addLayerEvent() { return new UIEvent( EV_ADD_LAYER ); }
+ public static UIEvent removeLayerEvent() { return new UIEvent( EV_REMOVE_LAYER ); }
+ public static UIEvent selectLayer( MapLayer layer ) { return new LayerEvent( EV_SELECT_LAYER, layer ); }
+ public static UIEvent hideLayer( MapLayer layer ) { return new LayerEvent( EV_HIDE_LAYER, layer ); }
+ public static UIEvent showLayer( MapLayer layer ) { return new LayerEvent( EV_SHOW_LAYER, layer ); }
+ public static UIEvent addImageEvent( FileHandle file ) { return new FileEvent( EV_ADD_IMAGE, file ); }
+ public static UIEvent selectObject( MapObject object ) { return new MapObjectEvent( EV_SELECT_MAP_OBJECT, object ); }
+ public static UIEvent selectImagePath( FileHandle file ) { return new FileEvent( EV_SELECT_IMAGE_PATH, file ); }
+}
diff --git a/maps-editor/src/com/mobidevelop/utils/commands/Command.java b/maps-editor/src/com/mobidevelop/utils/commands/Command.java
index ccba5eb..12d11f6 100644
--- a/maps-editor/src/com/mobidevelop/utils/commands/Command.java
+++ b/maps-editor/src/com/mobidevelop/utils/commands/Command.java
@@ -16,6 +16,8 @@
package com.mobidevelop.utils.commands;
+import com.mobidevelop.utils.events.Event;
+
/**
* Represents an action that can be executed and reversed.
*
@@ -23,8 +25,8 @@
*/
public interface Command {
- public void execute();
+ public Event execute();
- public void reverse();
+ public Event reverse();
}
diff --git a/maps-editor/src/com/mobidevelop/utils/commands/CommandManager.java b/maps-editor/src/com/mobidevelop/utils/commands/CommandManager.java
index 5c14482..d8b03d8 100644
--- a/maps-editor/src/com/mobidevelop/utils/commands/CommandManager.java
+++ b/maps-editor/src/com/mobidevelop/utils/commands/CommandManager.java
@@ -18,6 +18,9 @@
import java.util.*;
+import com.mobidevelop.maps.editor.models.MapModels.MapModel;
+import com.mobidevelop.utils.events.Event;
+
/**
* The {@code CommandManager} class manages the execution and reversal of {@link Command Commands}.
@@ -28,8 +31,11 @@ public class CommandManager {
private Deque undoStack;
private Deque redoStack;
-
- public CommandManager() {
+
+ private MapModel model;
+
+ public CommandManager( MapModel model ) {
+ this.model = model;
undoStack = new ArrayDeque();
redoStack = new ArrayDeque();
}
@@ -40,7 +46,9 @@ public CommandManager() {
* @param command The {@link Command} to execute.
*/
public void execute(Command command) {
- command.execute();
+ Event event = command.execute();
+ if ( event != null )
+ model.dispatchEvent( event );
undoStack.push(command);
redoStack.clear();
}
@@ -55,7 +63,9 @@ public void undo() {
throw new RuntimeException("No commands to undo.");
}
Command command = undoStack.pop();
- command.reverse();
+ Event event = command.reverse();
+ if ( event != null )
+ model.dispatchEvent( event );
redoStack.push(command);
}
@@ -70,7 +80,9 @@ public void undo(int count) {
}
while (!undoStack.isEmpty() && count > 0) {
Command command = undoStack.pop();
- command.reverse();
+ Event event = command.reverse();
+ if ( event != null )
+ model.dispatchEvent( event );
redoStack.push(command);
count--;
}
@@ -103,7 +115,9 @@ public void redo() {
throw new RuntimeException("No commands to redo.");
}
Command command = redoStack.pop();
- command.execute();
+ Event event = command.execute();
+ if ( event != null )
+ model.dispatchEvent( event );
undoStack.push(command);
}
@@ -113,7 +127,9 @@ public void redo(int count) {
}
while (!undoStack.isEmpty() && count > 0) {
Command command = redoStack.pop();
- command.execute();
+ Event event = command.execute();
+ if ( event != null )
+ model.dispatchEvent( event );
undoStack.push(command);
count--;
}
diff --git a/maps/src/com/mobidevelop/maps/Map.java b/maps/src/com/mobidevelop/maps/Map.java
index 0e8d1b1..ea4b95d 100644
--- a/maps/src/com/mobidevelop/maps/Map.java
+++ b/maps/src/com/mobidevelop/maps/Map.java
@@ -46,4 +46,5 @@ public interface Map extends Disposable {
public abstract MapResources getResources();
+ public abstract MapLayer createLayer( String name );
}