/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2013 Ausenco Engineering Canada Inc.
* Copyright (C) 2016 JaamSim Software Inc.
*
* 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.jaamsim.ui;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
import com.jaamsim.DisplayModels.ColladaModel;
import com.jaamsim.DisplayModels.ImageModel;
import com.jaamsim.Graphics.DisplayEntity;
import com.jaamsim.basicsim.Entity;
import com.jaamsim.controllers.RenderManager;
import com.jaamsim.input.InputAgent;
import com.jaamsim.input.KeywordIndex;
import com.jaamsim.math.AABB;
import com.jaamsim.math.Vec2d;
import com.jaamsim.math.Vec3d;
import com.jaamsim.render.MeshProtoKey;
import com.jaamsim.render.RenderUtils;
/**
* Creates entities from a 3D asset file (.DAE, .OBJ, etc.) or a image file (.png, .jpg, etc.).
*
* @author matt.chudleigh
*
*/
public class DisplayEntityFactory extends Entity {
private static File lastDir; // Last directory selected by the file chooser
/**
* Opens a FileDialog for selecting images to import.
*
* @param gui - the Control Panel.
*/
public static void importImages(GUIFrame gui) {
// Create a file chooser
final JFileChooser chooser = new JFileChooser(lastDir);
chooser.setMultiSelectionEnabled(true);
// Set the file extension filters
chooser.setAcceptAllFileFilterUsed(false);
FileNameExtensionFilter[] imgFilters = ImageModel.getFileNameExtensionFilters();
for (int i = 0; i < imgFilters.length; i++) {
chooser.addChoosableFileFilter(imgFilters[i]);
}
chooser.setFileFilter(imgFilters[0]);
// Show the file chooser and wait for selection
int returnVal = chooser.showDialog(gui, "Import Images");
// Create the selected graphics files
if (returnVal == JFileChooser.APPROVE_OPTION) {
File[] files = chooser.getSelectedFiles();
lastDir = chooser.getCurrentDirectory();
DisplayEntityFactory.importImageFiles(files);
}
}
/**
* Opens a FileDialog for selecting 3D assets to import.
*
* @param gui - the Control Panel.
*/
public static void import3D(GUIFrame gui) {
// Create a file chooser
final JFileChooser chooser = new JFileChooser(lastDir);
chooser.setMultiSelectionEnabled(true);
// Set the file extension filters
chooser.setAcceptAllFileFilterUsed(false);
FileNameExtensionFilter[] colFilters = ColladaModel.getFileNameExtensionFilters();
chooser.addChoosableFileFilter(colFilters[0]);
for (int i = 1; i < colFilters.length; i++) {
chooser.addChoosableFileFilter(colFilters[i]);
}
chooser.setFileFilter(colFilters[0]);
// Show the file chooser and wait for selection
int returnVal = chooser.showDialog(gui, "Import 3D Assets");
// Create the selected graphics files
if (returnVal == JFileChooser.APPROVE_OPTION) {
File[] files = chooser.getSelectedFiles();
lastDir = chooser.getCurrentDirectory();
DisplayEntityFactory.import3DFiles(files);
}
}
/**
* Creates a new thread for creating the imported images.
*
* @param files - the image files to import
*/
private static void importImageFiles(File[] files) {
final File[] chosenfiles = files;
new Thread(new Runnable() {
@Override
public void run() {
DisplayEntityFactory.createImages(chosenfiles);
}
}).start();
}
/**
* Creates a new thread for creating the 3D assets.
*
* @param files - the 3D asset files to import
*/
private static void import3DFiles(File[] files) {
final File[] chosenfiles = files;
new Thread(new Runnable() {
@Override
public void run() {
DisplayEntityFactory.create3DAssets(chosenfiles);
}
}).start();
}
/**
* Loops through the specified files and creates a new DisplayEntity for each one.
*
* @param files - the image files
*/
private static void createImages(File[] files) {
if (!RenderManager.isGood()) {
GUIFrame.invokeErrorDialog("Runtime Error", "The renderer is not ready.");
return;
}
// Loop through the graphics files
for (File f : files) {
// Determine the file name and extension
String fileName = f.getName();
int i = fileName.lastIndexOf('.');
if (i <= 0 || i >= fileName.length() - 1) {
GUIFrame.invokeErrorDialog("Input Error",
"File name: %s is invalid.", f.getName());
continue;
}
String extension = fileName.substring(i+1).toLowerCase();
if (!ImageModel.isValidExtension(extension)) {
GUIFrame.invokeErrorDialog("Input Error",
"The extension for file: %s is invalid for an image.", fileName);
continue;
}
// Set the entity name
String entityName = fileName.substring(0, i);
entityName = entityName.replaceAll(" ", "_"); // Space is not allowed for Entity Name
// Create the ImageModel
String modelName = entityName + "-model";
ImageModel dm = InputAgent.defineEntityWithUniqueName(ImageModel.class, modelName, "", true);
// Load the image to the ImageModel
InputAgent.applyArgs(dm, "ImageFile", f.getPath());
// Create the DisplayEntity
DisplayEntity de = InputAgent.defineEntityWithUniqueName(DisplayEntity.class, entityName, "", true);
// Assign the ImageModel to the new DisplayEntity
InputAgent.applyArgs(de, "DisplayModel", dm.getName());
// Set the x-dimension of the image to maintain its aspect ratio
Vec3d size = new Vec3d(1.0, 1.0, 0.0);
Vec2d imageDims = RenderManager.inst().getImageDims(f.toURI());
if (imageDims != null)
size.x = imageDims.x / imageDims.y;
KeywordIndex kw = InputAgent.formatPointInputs("Size", size, "m");
InputAgent.apply(de, kw);
}
}
/**
* Loops through the specified files and creates a new DisplayEntity for each one.
*
* @param files - the 3D asset and/or image files.
*/
private static void create3DAssets(File[] files) {
if (!RenderManager.isGood()) {
GUIFrame.invokeErrorDialog("Runtime Error", "The renderer is not ready.");
return;
}
// Loop through the graphics files
for (File f : files) {
// Determine the file name and extension
String fileName = f.getName();
int i = fileName.lastIndexOf('.');
if (i <= 0 || i >= fileName.length() - 1) {
GUIFrame.invokeErrorDialog("Input Error",
"File name: %s is invalid.", f.getName());
continue;
}
String extension = fileName.substring(i+1).toLowerCase();
if (!ColladaModel.isValidExtension(extension)) {
GUIFrame.invokeErrorDialog("Input Error",
"The extension for file: %s is invalid for a 3D asset.", fileName);
continue;
}
// Set the entity name
String entityName = fileName.substring(0, i);
entityName = entityName.replaceAll(" ", "_"); // Space is not allowed for Entity Name
// Create the ColladaModel
String modelName = entityName + "-model";
ColladaModel dm = InputAgent.defineEntityWithUniqueName(ColladaModel.class, modelName, "", true);
// Load the 3D content to the ColladaModel
InputAgent.applyArgs(dm, "ColladaFile", f.getPath());
// Create the DisplayEntity
DisplayEntity de = InputAgent.defineEntityWithUniqueName(DisplayEntity.class, entityName, "", true);
// Assign the ColladaModel to the new DisplayEntity
InputAgent.applyArgs(de, "DisplayModel", dm.getName());
// Calculate the DisplayEntity's size and position from the ColladaModel
MeshProtoKey meshKey = RenderUtils.FileNameToMeshProtoKey(f.toURI());
AABB modelBounds = RenderManager.inst().getMeshBounds(meshKey, true);
Vec3d entityPos = modelBounds.center;
Vec3d modelSize = new Vec3d(modelBounds.radius);
modelSize.scale3(2);
// Set the DisplayEntity's position, size, and alignment
KeywordIndex kw;
kw = InputAgent.formatPointInputs("Position", entityPos, "m");
InputAgent.apply(de, kw);
kw = InputAgent.formatPointInputs("Alignment", new Vec3d(), null);
InputAgent.apply(de, kw);
kw = InputAgent.formatPointInputs("Size", modelSize, "m");
InputAgent.apply(de, kw);
}
}
}