package com.vitco.core;
import com.vitco.core.data.container.VOXELMODE;
import com.vitco.core.data.notification.DataChangeAdapter;
import com.vitco.core.modes.AbstractAdapter;
import com.vitco.core.modes.AnimationAdapter;
import com.vitco.core.modes.VoxelAdapter;
import com.vitco.core.modes.tools.*;
import com.vitco.manager.pref.PrefChangeListener;
import com.vitco.settings.VitcoSettings;
import javax.annotation.PostConstruct;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.HashMap;
/**
* Defines general (common) interactions available for this engine view and sets them up.
*/
public abstract class EngineInteractionPrototype extends EngineViewPrototype {
// constructor
protected EngineInteractionPrototype(Integer side) {
super(side);
}
// list of tool mappings
private final HashMap<VOXELMODE, AbstractTool> toolMapping = new HashMap<VOXELMODE, AbstractTool>();
// current mode
protected VOXELMODE voxelMode = VitcoSettings.INITIAL_VOXEL_MODE;
// ===============================
// Animation
// ===============================
// animation adapter
protected final AnimationAdapter animationAdapter = new AnimationAdapter(container);
// ===============================
// Voxel
// ===============================
// voxel draw adapter for main view
protected final VoxelAdapter voxelAdapter = new VoxelAdapter(container);
private static boolean initialized = false;
@PostConstruct
protected final void init() {
if (!initialized) {
initialized = true;
// register shortcuts for shifting the selection
actionManager.registerAction("shift_selected_voxels_up", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (data.anyVoxelSelected()) {
int[] shift = data.getVoxelSelectionShift();
data.setVoxelSelectionShift(shift[0], shift[1]+1, shift[2]);
}
}
});
// register shortcuts for shifting the selection
actionManager.registerAction("shift_selected_voxels_down", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (data.anyVoxelSelected()) {
int[] shift = data.getVoxelSelectionShift();
data.setVoxelSelectionShift(shift[0], shift[1] - 1, shift[2]);
}
}
});
// register shortcuts for shifting the selection
actionManager.registerAction("shift_selected_voxels_left", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (data.anyVoxelSelected()) {
int[] shift = data.getVoxelSelectionShift();
data.setVoxelSelectionShift(shift[0], shift[1], shift[2] - 1);
}
}
});
// register shortcuts for shifting the selection
actionManager.registerAction("shift_selected_voxels_right", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (data.anyVoxelSelected()) {
int[] shift = data.getVoxelSelectionShift();
data.setVoxelSelectionShift(shift[0], shift[1], shift[2] + 1);
}
}
});
// register shortcuts for shifting the selection
actionManager.registerAction("shift_selected_voxels_out", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (data.anyVoxelSelected()) {
int[] shift = data.getVoxelSelectionShift();
data.setVoxelSelectionShift(shift[0] + 1, shift[1], shift[2]);
}
}
});
// register shortcuts for shifting the selection
actionManager.registerAction("shift_selected_voxels_in", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (data.anyVoxelSelected()) {
int[] shift = data.getVoxelSelectionShift();
data.setVoxelSelectionShift(shift[0] - 1, shift[1], shift[2]);
}
}
});
// set the voxel snap preference (if not set)
if (!preferences.contains("voxel_snap_enabled")) {
preferences.storeBoolean("voxel_snap_enabled", VitcoSettings.INITIAL_ANIMATION_VOXEL_SNAP);
}
// initialize the data mapping for all adapters
AbstractAdapter.setAsyncActionManager(asyncActionManager);
// initialize the data mapping for all tools
AbstractTool.setData(data);
AbstractTool.setPreferences(preferences);
AbstractTool.setAsyncActionManager(asyncActionManager);
AbstractTool.setActionManager(actionManager);
AbstractTool.setLangSelector(langSelector);
}
// initialize the tool mapping
ViewTool viewTool = new ViewTool(container, side);
toolMapping.put(VOXELMODE.VIEW, viewTool);
toolMapping.put(VOXELMODE.DRAW, new DrawTool(container, side));
toolMapping.put(VOXELMODE.ERASE, new EraseTool(container, side));
toolMapping.put(VOXELMODE.PICKER, new PickerTool(container, side));
toolMapping.put(VOXELMODE.COLORCHANGER, new ColorChangerTool(container, side));
toolMapping.put(VOXELMODE.FLOODFILL, new FloodFillTool(container, side));
toolMapping.put(VOXELMODE.SELECT, new SelectTool(container, side));
// make sure the missing modes have the view tool assigned
for (VOXELMODE mode : VOXELMODE.values()) {
if (!toolMapping.containsKey(mode)) {
System.err.println("Tool \"" + mode + "\" uses the default functionality.");
toolMapping.put(mode, viewTool);
}
}
// set the default mode
voxelAdapter.setTool(toolMapping.get(voxelMode));
// set the default animation tool
animationAdapter.setTool(new PointTool(container, side));
// what to do when data changes
DataChangeAdapter dca = new DataChangeAdapter() {
@Override
public void onAnimationDataChanged() {
container.refresh2DIndex();
container.skipNextWorldRender(); // no need to re-render scene
forceRepaint();
}
@Override
public void onAnimationSelectionChanged() {
container.skipNextWorldRender(); // no need to re-render scene
forceRepaint();
}
@Override
public void onVoxelDataChanged() {
// reset shift of voxels selection
data.setVoxelSelectionShift(0,0,0);
invalidateVoxels();
container.doNotSkipNextWorldRender();
forceRepaint();
}
@Override
public void onVoxelHighlightingChanged() {
container.updateHighlightedVoxel();
container.skipNextWorldRender();
forceRepaint();
}
@Override
public void onVoxelSelectionShiftChanged() {
int[] shift = data.getVoxelSelectionShift();
selectedVoxelsWorld.setShift(shift);
container.doNotSkipNextWorldRender();
forceRepaint();
}
@Override
public void onTextureDataChanged() {
invalidateVoxels();
container.doNotSkipNextWorldRender();
forceRepaint();
}
@Override
public void onOutlineBoxesChanged() {
container.updateOutlineBoxes();
container.skipNextWorldRender();
forceRepaint();
}
@Override
public void onSelectionRectChanged() {
container.updateSelectedRect();
container.skipNextWorldRender();
forceRepaint();
}
};
data.addDataChangeListener(dca);
// logic to switch between voxel and animation modification tools
preferences.addPrefChangeListener("is_animation_mode_active", new PrefChangeListener() {
@Override
public void onPrefChange(Object newValue) {
boolean isAnimate = (Boolean)newValue;
if (isAnimate) {
data.removeVoxelHighlights();
removeAll();
container.addMouseMotionListener(animationAdapter);
container.addMouseListener(animationAdapter);
animationAdapter.activate();
} else {
data.removeAnimationHighlights();
removeAll();
container.addMouseMotionListener(voxelAdapter);
container.addMouseListener(voxelAdapter);
voxelAdapter.activate();
}
container.setDrawAnimationOverlay(isAnimate);
container.setDrawSelectedVoxels(!isAnimate);
// was added since there were some problems with selecting/deselecting in the side view
container.doNotSkipNextWorldRender();
forceRepaint();
}
private void removeAll() {
// just to be sure there are no listeners left
voxelAdapter.deactivate();
container.removeMouseMotionListener(voxelAdapter);
container.removeMouseListener(voxelAdapter);
animationAdapter.deactivate();
container.removeMouseMotionListener(animationAdapter);
container.removeMouseListener(animationAdapter);
}
});
// initialize listener adapter
if (!preferences.contains("is_animation_mode_active")) {
preferences.storeObject("is_animation_mode_active", VitcoSettings.INITIAL_MODE_IS_ANIMATION);
}
// register change of voxel mode
preferences.addPrefChangeListener("active_voxel_submode", new PrefChangeListener() {
@Override
public void onPrefChange(Object newValue) {
voxelMode = (VOXELMODE) newValue;
voxelAdapter.setTool(toolMapping.get(voxelMode));
forceRepaint();
}
});
}
}