/**
* eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the
* <e-UCM> research group.
*
* Copyright 2005-2010 <e-UCM> research group.
*
* You can access a list of all the contributors to eAdventure at:
* http://e-adventure.e-ucm.es/contributors
*
* <e-UCM> is a research group of the Department of Software Engineering
* and Artificial Intelligence at the Complutense University of Madrid
* (School of Computer Science).
*
* C Profesor Jose Garcia Santesmases sn,
* 28040 Madrid (Madrid), Spain.
*
* For more info please visit: <http://e-adventure.e-ucm.es> or
* <http://www.e-ucm.es>
*
* ****************************************************************************
*
* This file is part of eAdventure, version 2.0
*
* eAdventure is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* eAdventure is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with eAdventure. If not, see <http://www.gnu.org/licenses/>.
*/
package ead.importer.subimporters.chapter.scene;
import com.google.inject.Inject;
import ead.importer.EAdElementImporter;
import ead.importer.annotation.ImportAnnotator;
import ead.importer.interfaces.EAdElementFactory;
import ead.importer.interfaces.ResourceImporter;
import es.eucm.ead.model.assets.drawable.basics.Image;
import es.eucm.ead.model.assets.multimedia.EAdSound;
import es.eucm.ead.model.assets.multimedia.Sound;
import es.eucm.ead.model.elements.conditions.ANDCond;
import es.eucm.ead.model.elements.conditions.EmptyCond;
import es.eucm.ead.model.elements.conditions.NOTCond;
import es.eucm.ead.model.elements.effects.TriggerMacroEf;
import es.eucm.ead.model.elements.effects.variables.ChangeFieldEf;
import es.eucm.ead.model.elements.events.SceneElementEv;
import es.eucm.ead.model.elements.events.enums.SceneElementEvType;
import es.eucm.ead.model.elements.extra.EAdList;
import es.eucm.ead.model.elements.predef.effects.MakeActiveElementEf;
import es.eucm.ead.model.elements.predef.effects.MoveActiveElementToMouseEf;
import es.eucm.ead.model.elements.predef.events.ScrollWithSceneElementEv;
import es.eucm.ead.model.elements.scenes.*;
import es.eucm.ead.model.elements.trajectories.NodeTrajectory;
import es.eucm.ead.model.elements.trajectories.SimpleTrajectory;
import es.eucm.ead.model.params.guievents.MouseGEv;
import es.eucm.ead.model.params.text.EAdString;
import es.eucm.ead.model.params.util.Position;
import es.eucm.ead.model.params.util.Position.Corner;
import es.eucm.ead.tools.StringHandler;
import es.eucm.eadventure.common.data.chapter.Chapter;
import es.eucm.eadventure.common.data.chapter.ElementReference;
import es.eucm.eadventure.common.data.chapter.Exit;
import es.eucm.eadventure.common.data.chapter.Trajectory;
import es.eucm.eadventure.common.data.chapter.conditions.Conditions;
import es.eucm.eadventure.common.data.chapter.elements.ActiveArea;
import es.eucm.eadventure.common.data.chapter.elements.Barrier;
import es.eucm.eadventure.common.data.chapter.elements.Player;
import es.eucm.eadventure.common.data.chapter.resources.Resources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Scenes importer
*
*/
public class SceneImporter implements EAdElementImporter<es.eucm.eadventure.common.data.chapter.scenes.Scene, Scene> {
static private Logger logger = LoggerFactory.getLogger(SceneImporter.class);
/**
* String handler
*/
private StringHandler stringHandler;
/**
* References importer
*/
private EAdElementImporter<ElementReference, SceneElement> referencesImporter;
/**
* Resources importer
*/
private ResourceImporter resourceImporter;
/**
* Exits importer
*/
private EAdElementImporter<Exit, SceneElement> exitsImporter;
/**
* Trajectory importer
*/
private EAdElementImporter<Trajectory, NodeTrajectory> trajectoryImporter;
/**
* Barrier importer
*/
private EAdElementImporter<Barrier, SceneElement> barrierImporter;
private EAdElementFactory factory;
protected ImportAnnotator annotator;
private EAdElementImporter<Conditions, Condition> conditionsImporter;
@Inject
public SceneImporter(
StringHandler stringHandler,
EAdElementImporter<Conditions, Condition> conditionsImporter,
ResourceImporter resourceImporter,
EAdElementImporter<ElementReference, SceneElement> referencesImporter,
EAdElementFactory factory,
EAdElementImporter<Exit, SceneElement> exitsImporter,
EAdElementImporter<Trajectory, NodeTrajectory> trajectoryImporter,
EAdElementImporter<Barrier, SceneElement> barrierImporter,
ImportAnnotator annotator) {
this.stringHandler = stringHandler;
this.resourceImporter = resourceImporter;
this.exitsImporter = exitsImporter;
this.referencesImporter = referencesImporter;
this.trajectoryImporter = trajectoryImporter;
this.barrierImporter = barrierImporter;
this.factory = factory;
this.annotator = annotator;
this.conditionsImporter = conditionsImporter;
}
@Override
public Scene init(es.eucm.eadventure.common.data.chapter.scenes.Scene oldScene) {
Scene scene = new Scene();
return scene;
}
@Override
public Scene convert(es.eucm.eadventure.common.data.chapter.scenes.Scene oldScene, Object object) {
Chapter chapter = factory.getCurrentChapterModel();
Scene scene = (Scene) object;
//chapter.getScenes().add(scene);
importDocumentation(scene, oldScene);
importResources(scene, oldScene, chapter);
importSceneElements(scene, oldScene, chapter);
return scene;
}
private void importSceneElements(Scene scene, es.eucm.eadventure.common.data.chapter.scenes.Scene oldScene,
Chapter chapter) {
int substract = importActiveAreas(1, scene, oldScene.getActiveAreas());
importExits(substract, scene, oldScene.getExits());
importReferences(scene, oldScene.getItemReferences(), chapter);
importReferences(scene, oldScene.getAtrezzoReferences(), chapter);
importReferences(scene, oldScene.getCharacterReferences(), chapter);
SceneElement playerReference = addPlayer(scene, oldScene, chapter);
importTrajectory(scene, oldScene.getTrajectory(), oldScene
.getBarriers(), playerReference);
}
private SceneElement addPlayer(Scene scene, es.eucm.eadventure.common.data.chapter.scenes.Scene oldScene,
Chapter chapter) {
if (factory.isFirstPerson()) {
return null;
} else {
SceneElementDef player = (SceneElementDef) factory
.getElementById(Player.IDENTIFIER);
SceneElement playerReference = new SceneElement(player);
Position p = new Position(Position.Corner.BOTTOM_CENTER, oldScene
.getPositionX(), oldScene.getPositionY());
playerReference.setPosition(p);
playerReference.setScale(oldScene.getPlayerScale());
// Make it active element of the scene
MakeActiveElementEf effect = new MakeActiveElementEf(
playerReference);
SceneElementEv event = new SceneElementEv();
event.addEffect(SceneElementEvType.INIT, effect);
playerReference.addEvent(event);
int playerZ = oldScene.isAllowPlayerLayer() ? Math.max(0, oldScene
.getPlayerLayer()) : 1;
playerReference.setVarInitialValue(SceneElement.VAR_Z, playerZ);
scene.getSceneElements().add(playerReference);
scene.getBackground().addBehavior(MouseGEv.MOUSE_LEFT_PRESSED,
new MoveActiveElementToMouseEf());
// Add move camera with character
Dimension d = resourceImporter.getDimensionsForOldImage(oldScene
.getResources().get(0).getAssetPath(
es.eucm.eadventure.common.data.chapter.scenes.Scene.RESOURCE_TYPE_BACKGROUND));
scene.setBounds(d.width, 600);
ScrollWithSceneElementEv scroll = new ScrollWithSceneElementEv(
scene, playerReference);
scene.addEvent(scroll);
return playerReference;
}
}
private void importTrajectory(Scene scene, Trajectory trajectory,
List<Barrier> barriers, SceneElement playerReference) {
if (trajectory == null) {
scene.setTrajectoryDefinition(new SimpleTrajectory(true));
} else {
NodeTrajectory nodeDef = trajectoryImporter.init(trajectory);
nodeDef = trajectoryImporter.convert(trajectory, nodeDef);
scene.setTrajectoryDefinition(nodeDef);
for (Barrier b : barriers) {
SceneElement barrier = barrierImporter.init(b);
barrier = barrierImporter.convert(b, barrier);
nodeDef.addBarrier(barrier);
scene.getSceneElements().add(barrier);
}
playerReference.setPosition(new Position(Corner.BOTTOM_CENTER,
nodeDef.getInitial().getX(), nodeDef.getInitial().getY()));
playerReference.setScale(nodeDef.getInitial().getScale());
}
}
private int importActiveAreas(int substract, Scene scene,
List<ActiveArea> list) {
int i = 0;
for (ActiveArea a : list) {
SceneElement activeArea = (SceneElement) factory.getElementById(a
.getId());
activeArea.setPosition(new Position(Position.Corner.TOP_LEFT, a
.getX(), a.getY()));
activeArea.setVarInitialValue(SceneElement.VAR_Z, Integer.MAX_VALUE
- substract - i);
i++;
if (activeArea != null)
scene.getSceneElements().add(activeArea);
}
return substract - i;
}
private int importExits(int substract, Scene scene, List<Exit> list) {
int i = 0;
for (Exit e : list) {
SceneElement se = exitsImporter.init(e);
se.setVarInitialValue(SceneElement.VAR_Z, Integer.MAX_VALUE
- substract - i);
se = exitsImporter.convert(e, se);
i++;
if (se != null) {
scene.getSceneElements().add(se);
}
}
return substract - i;
}
private void importReferences(Scene scene,
List<ElementReference> references, Chapter chapter) {
for (ElementReference oldRef : references) {
SceneElement newRef = referencesImporter.init(oldRef);
newRef = referencesImporter.convert(oldRef, newRef);
newRef.setVarInitialValue(SceneElement.VAR_Z, oldRef.getLayer());
scene.getSceneElements().add(newRef);
}
}
private void importResources(Scene scene, es.eucm.eadventure.common.data.chapter.scenes.Scene oldScene,
Chapter chapter) {
Map<String, String> resourcesStrings = new LinkedHashMap<String, String>();
resourcesStrings.put(es.eucm.eadventure.common.data.chapter.scenes.Scene.RESOURCE_TYPE_BACKGROUND,
SceneElementDef.appearance);
Map<String, Object> resourcesClasses = new LinkedHashMap<String, Object>();
resourcesClasses.put(es.eucm.eadventure.common.data.chapter.scenes.Scene.RESOURCE_TYPE_BACKGROUND, Image.class);
resourceImporter.importResources(scene.getBackground().getDefinition(),
oldScene.getResources(), resourcesStrings, resourcesClasses);
// Music variables
List<String> musics = new ArrayList<String>();
List<Condition> conditions = new ArrayList<Condition>();
Condition lastCondition = null;
boolean end = false;
for (Resources r : oldScene.getResources()) {
Condition c = conditionsImporter.init(r.getConditions());
c = conditionsImporter.convert(r.getConditions(), c);
// This condition is to detect if the resources blocks has an empty
// condition. If so, subsequent resources blocks are unreachable
if (c.equals(EmptyCond.TRUE)) {
end = true;
}
if (lastCondition != null) {
c = new ANDCond(new NOTCond(lastCondition), c);
lastCondition = c;
}
conditions.add(c);
String foregroundPath = r
.getAssetPath(es.eucm.eadventure.common.data.chapter.scenes.Scene.RESOURCE_TYPE_FOREGROUND);
if (foregroundPath != null) {
Image image = (Image) resourceImporter.getAssetDescritptor(
foregroundPath, Image.class);
String path = image.getUri();
if (path.endsWith(".jpg") || path.endsWith(".JPG")) {
image = new Image(path.substring(0, path.length() - 3)
+ "png");
}
String backgroundPath = r
.getAssetPath(es.eucm.eadventure.common.data.chapter.scenes.Scene.RESOURCE_TYPE_BACKGROUND);
applyForegroundMask(image.getUri(), foregroundPath,
backgroundPath);
SceneElement foreground = new SceneElement(image);
foreground.setVarInitialValue(SceneElement.VAR_Z,
Integer.MAX_VALUE);
foreground.setEnable(false);
ChangeFieldEf changeVisibility = new ChangeFieldEf(foreground
.getField(SceneElement.VAR_VISIBLE), c);
SceneElementEv event = new SceneElementEv(
SceneElementEvType.ALWAYS, changeVisibility);
foreground.addEvent(event);
scene.getSceneElements().add(foreground);
}
musics.add(r.getAssetPath(es.eucm.eadventure.common.data.chapter.scenes.Scene.RESOURCE_TYPE_MUSIC));
if (end) {
break;
}
}
importSceneMusic(musics, resourceImporter, scene, conditions);
}
public static void importSceneMusic(List<String> musicPaths,
ResourceImporter resourceImporter, Scene scene,
List<Condition> conditions) {
TriggerMacroEf triggerMacro = new TriggerMacroEf();
int i = 0;
for (String musicPath : musicPaths) {
Condition condition = conditions.get(i);
EAdSound sound = null;
if (musicPath != null) {
sound = (EAdSound) resourceImporter.getAssetDescritptor(
musicPath, Sound.class);
}
//PlayMusicEf playMusic = new PlayMusicEf(null, true, 1.0f);
triggerMacro.putEffects(condition, new EAdList<Effect>());
i++;
}
SceneElementEv event = new SceneElementEv();
event.addEffect(SceneElementEvType.ADDED, triggerMacro);
scene.addEvent(event);
}
private void applyForegroundMask(String finalPath, String foregroundPath,
String backgroundPath) {
BufferedImage foreground = resourceImporter.getOldImage(foregroundPath);
BufferedImage background = resourceImporter.getOldImage(backgroundPath);
int width = foreground.getWidth();
int height = foreground.getHeight();
int[] backgroundPixels = background.getRGB(0, 0, width, height, null,
0, width);
int[] maskPixels = foreground.getRGB(0, 0, width, height, null, 0,
width);
int[] resultPixels = new int[maskPixels.length];
for (int i = 0; i < backgroundPixels.length; i++) {
int color = backgroundPixels[i];
int mask = maskPixels[i];
if (mask != 0xffffffff) {
resultPixels[i] = color;
} else {
resultPixels[i] = 0x00000000;
}
}
BufferedImage result = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
result.getRaster().setDataElements(0, 0, width, height, resultPixels);
String newUri = resourceImporter.getString(foregroundPath);
try {
ImageIO.write(result, "png", new File(resourceImporter
.getNewProjecFolder(), newUri.substring(1)));
} catch (IOException e) {
logger.error("Error creating foreground image {}", e);
}
foreground.flush();
background.flush();
result.flush();
}
private void importDocumentation(Scene scene, es.eucm.eadventure.common.data.chapter.scenes.Scene oldScene) {
EAdString doc = stringHandler.generateNewString();
stringHandler.setString(doc, oldScene.getDocumentation());
scene.getDefinition().setDoc(doc);
EAdString name = stringHandler.generateNewString();
stringHandler.setString(name, oldScene.getName());
scene.getDefinition().setName(name);
}
}