/*******************************************************************************
* 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.engineeditor.ui;
import com.badlogic.gdx.Gdx;
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.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Container;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Scaling;
import com.bladecoder.engine.actions.Param;
import com.bladecoder.engine.actions.Param.Type;
import com.bladecoder.engine.model.MusicDesc;
import com.bladecoder.engine.model.Scene;
import com.bladecoder.engine.model.SceneLayer;
import com.bladecoder.engine.model.World;
import com.bladecoder.engineeditor.Ctx;
import com.bladecoder.engineeditor.common.EditorLogger;
import com.bladecoder.engineeditor.common.ElementUtils;
import com.bladecoder.engineeditor.common.Message;
import com.bladecoder.engineeditor.model.Project;
import com.bladecoder.engineeditor.ui.panels.EditModelDialog;
import com.bladecoder.engineeditor.ui.panels.InputPanel;
import com.bladecoder.engineeditor.ui.panels.InputPanelFactory;
import com.bladecoder.engineeditor.undo.UndoCreateScene;
import com.bladecoder.engineeditor.undo.UndoEditScene;
public class EditSceneDialog extends EditModelDialog<World, Scene> {
public static final String INFO = "An adventure is composed of many scenes (rooms/screens).\n"
+ "Inside a scene, there are actors and a 'player'.\nThe player/user can interact with actors throught 'verbs'.";
private Image bgImage;
private Container<Image> infoContainer;
private TextureAtlas atlas;
private InputPanel id;
private InputPanel backgroundAtlas;
private InputPanel backgroundRegion;
private InputPanel depthVector;
private InputPanel state;
private InputPanel music;
private InputPanel loopMusic;
private InputPanel volumeMusic;
private InputPanel initialMusicDelay;
private InputPanel repeatMusicDelay;
private InputPanel stopWhenLeaving;
private InputPanel sceneSize;
@SuppressWarnings("unchecked")
public EditSceneDialog(Skin skin, World parent, Scene e) {
super(skin);
id = InputPanelFactory.createInputPanel(skin, "Scene ID",
"The ID is mandatory for scenes.", true);
backgroundAtlas = InputPanelFactory.createInputPanel(skin, "Background Atlas",
"The atlas where the background for the scene is located", Type.ATLAS_ASSET, false);
backgroundRegion = InputPanelFactory.createInputPanel(skin, "Background Region Id",
"The region id for the background.", new String[0], false);
// depthVector = InputPanelFactory.createInputPanel(skin, "Depth Vector",
// "X: the actor 'y' position for a 0.0 scale, Y: the actor 'y' position for a 1.0 scale.",
// Param.Type.VECTOR2, false);
depthVector = InputPanelFactory.createInputPanel(skin, "Fake depth", "Change actor scale based in the 'y' axis position.", Param.Type.BOOLEAN, true,
"false");
state = InputPanelFactory.createInputPanel(skin, "State", "The initial state for the scene.", false);
music = InputPanelFactory.createInputPanel(skin, "Music Filename", "The music for the scene", Type.MUSIC_ASSET, false);
loopMusic = InputPanelFactory.createInputPanel(skin, "Loop Music", "If the music is playing in looping",
Param.Type.BOOLEAN, true, "true");
volumeMusic = InputPanelFactory.createInputPanel(skin, "Music Volume", "The volume of the music. Value is between 0 and 1.",
Param.Type.FLOAT, true, "1");
initialMusicDelay = InputPanelFactory.createInputPanel(skin, "Initial music delay",
"The time to wait before playing", Param.Type.FLOAT, true, "0");
repeatMusicDelay = InputPanelFactory.createInputPanel(skin, "Repeat music delay",
"The time to wait before repetitions", Param.Type.FLOAT, true, "-1");
stopWhenLeaving = InputPanelFactory.createInputPanel(skin, "Stop music when leaving",
"Stops the music when leaving the current scene.", Param.Type.BOOLEAN, true, "true");
sceneSize = InputPanelFactory.createInputPanel(skin, "Scene Dimension",
"Sets the size of the scene. If empty, the background image size is used as the scene dimension.",
Param.Type.DIMENSION, false);
bgImage = new Image();
bgImage.setScaling(Scaling.fit);
infoContainer = new Container<Image>(bgImage);
setInfo(INFO);
((SelectBox<String>) backgroundAtlas.getField()).addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
try {
fillBGRegions(backgroundAtlas, backgroundRegion);
} catch (Exception e) {
Message.showMsg(getStage(), "Error loading regions from selected atlas", 4);
}
}
});
((SelectBox<String>) backgroundRegion.getField()).addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
showBgImage(backgroundRegion.getText());
}
});
try {
fillBGRegions(backgroundAtlas, backgroundRegion);
} catch (Exception e2) {
EditorLogger.error("Error loading regions from selected atlas");
}
init(parent, e, new InputPanel[] { id, backgroundAtlas, backgroundRegion, depthVector, state, sceneSize, music,
loopMusic, volumeMusic, initialMusicDelay, repeatMusicDelay, stopWhenLeaving });
}
private void showBgImage(String r) {
if (atlas == null || r == null)
return;
bgImage.setDrawable(new TextureRegionDrawable(atlas.findRegion(r)));
infoContainer.prefWidth(250);
infoContainer.prefHeight(250);
setInfoWidget(infoContainer);
}
private void fillBGRegions(InputPanel atlasInput, InputPanel regionInput) {
@SuppressWarnings("unchecked")
SelectBox<String> cb = (SelectBox<String>) regionInput.getField();
// cb.clearItems();
cb.getItems().clear();
if (atlas != null) {
atlas.dispose();
atlas = null;
}
if (backgroundAtlas.getText().isEmpty()) {
setInfoWidget(new Label(INFO, getSkin()));
return;
}
atlas = new TextureAtlas(Gdx.files.absolute(Ctx.project.getProjectPath() + Project.ATLASES_PATH + "/"
+ Ctx.project.getResDir() + "/" + atlasInput.getText() + ".atlas"));
Array<AtlasRegion> regions = atlas.getRegions();
for (AtlasRegion r : regions)
if (cb.getItems().indexOf(r.name, false) == -1)
cb.getItems().add(r.name);
cb.getList().setItems(cb.getItems());
if (cb.getItems().size > 0)
cb.setSelectedIndex(0);
cb.invalidateHierarchy();
showBgImage(regionInput.getText());
}
@Override
protected void inputsToModel(boolean create) {
if (create) {
e = new Scene();
// CREATE DEFAULT LAYERS: BG, DYNAMIC, FG
SceneLayer l = new SceneLayer();
l.setName("foreground");
l.setVisible(true);
l.setDynamic(false);
e.addLayer(l);
l = new SceneLayer();
l.setName("dynamic");
l.setVisible(true);
l.setDynamic(true);
e.addLayer(l);
l = new SceneLayer();
l.setName("background");
l.setVisible(true);
l.setDynamic(false);
e.addLayer(l);
} else {
parent.getScenes().remove(e.getId());
}
e.setId(ElementUtils.getCheckedId(id.getText(), World.getInstance().getScenes().keySet().toArray(new String[0])));
e.setBackgroundAtlas(backgroundAtlas.getText());
e.setBackgroundRegionId(backgroundRegion.getText());
boolean dv = Boolean.parseBoolean(depthVector.getText());
if(dv == true && e.getDepthVector() == null) { // create depth vector
e.setDepthVector(new Vector2(World.getInstance().getHeight(), 0));
} else if(dv == false && e.getDepthVector() != null) { // Remove depth vector
e.setDepthVector(null);
}
e.setState(state.getText());
MusicDesc md = null;
if (music.getText() != null) {
md = new MusicDesc();
md.setFilename(music.getText());
md.setLoop(Boolean.parseBoolean(loopMusic.getText()));
md.setVolume(Float.parseFloat(volumeMusic.getText()));
md.setInitialDelay(Float.parseFloat(initialMusicDelay.getText()));
md.setRepeatDelay(Float.parseFloat(repeatMusicDelay.getText()));
md.setStopWhenLeaving(Boolean.parseBoolean(stopWhenLeaving.getText()));
}
e.setMusicDesc(md);
e.setSceneSize(Param.parseVector2(sceneSize.getText()));
parent.addScene(e);
if (parent.getScenes().size() == 1)
parent.setInitScene(e.getId());
// UNDO OP
if (create) {
Ctx.project.getUndoStack().add(new UndoCreateScene(e));
} else {
Ctx.project.getUndoStack().add(new UndoEditScene(e));
}
Ctx.project.setModified(this, Project.NOTIFY_ELEMENT_CREATED, null, e);
}
@Override
protected void modelToInputs() {
id.setText(e.getId());
backgroundAtlas.setText(e.getBackgroundAtlas());
backgroundRegion.setText(e.getBackgroundRegionId());
if (e.getDepthVector() != null)
depthVector.setText("true");
else
depthVector.setText("false");
state.setText(e.getState());
MusicDesc md = e.getMusicDesc();
if (md != null) {
music.setText(md.getFilename());
loopMusic.setText(Boolean.toString(md.isLoop()));
volumeMusic.setText(Float.toString(md.getVolume()));
initialMusicDelay.setText(Float.toString(md.getInitialDelay()));
repeatMusicDelay.setText(Float.toString(md.getRepeatDelay()));
stopWhenLeaving.setText(Boolean.toString(md.isStopWhenLeaving()));
}
if (e.getSceneSize() != null)
sceneSize.setText(Param.toStringParam(e.getSceneSize()));
}
@Override
protected void result(Object object) {
if (atlas != null) {
atlas.dispose();
}
super.result(object);
}
}