package core;
import gui.TimelineFolderDrawer;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
/* Timeline has its own modifiers, thus has to provide all preview functions available in MouseGesture
* sortedTimelineModifiersId stores the modifiers id sorted by offsetT for reading
* modifiers stores the modifier objects
* */
public class Timeline implements MouseGestureModifierParent, Serializable {
public static final int MODE_POINT = 0;
public static final int MODE_LINE = 1;
public static final int MODE_WHOLE = 2;
private long id;
private String name;
private int current;
private MouseGestureModifier currentModifier;
private boolean visible = true;
private MouseGesture mg;
private TimelineFolder folder;
private ArrayList<Long> sortedTimelineModifiersId;
private HashMap<Long, MouseGestureModifier> modifiers;
// rendering config
private int mode = MODE_POINT;
private boolean interpolation = false;
// status of the timeline at the end of each read(time)
/*
public static final int quiet = 0; // nothing to display at current time
public static final int beginning = 1; // beginning of the first occurrence of mousegesture in current timeline
public static final int active_gesture = 2; // occurrence of mousegesture visible at current time
public static final int end_of_gesture = 3; // end of current occurrence of mousegesture is reached, other occurrence are yet to come
public static final int end_of_gesture_and_beginning = 4; // end of current occurrence of mousegesture is reached, another occurrence begins right after
public static final int end_of_timeline = 5; // end of current occurrence of mousegesture is reached, nothing after this one in the timeline
private int status;
*/
public float[] color = new float[] {0,0,0,255};
public Timeline(MouseGesture mg, TimelineFolder folder) {
id = MGComposer.mgc.getUniqueId();
name = "line #"+this.id;
current = -1;
currentModifier = null;
this.mg = mg;
this.folder = folder;
// status = -1;
sortedTimelineModifiersId = new ArrayList<Long>();
modifiers = new HashMap<Long, MouseGestureModifier>();
addBlock();
}
public Timeline(Timeline tocopy, TimelineFolder folder) {
id = MGComposer.mgc.getUniqueId();
name = "line #"+this.id;
current = tocopy.getCurrent();
mg = tocopy.getMg();
this.folder = folder;
// status = tocopy.getStatus();
visible = tocopy.isVisible();
mode = tocopy.getMode();
interpolation = tocopy.isInterpolation();
currentModifier = null;
sortedTimelineModifiersId = new ArrayList<Long>();
modifiers = new HashMap<Long, MouseGestureModifier>();
for (int i=0; i<tocopy.getSortedTimelineModifiersId().size(); i++) {
long c = tocopy.getSortedTimelineModifiersId().get(i);
MouseGestureModifier m = tocopy.getModifiers().get(c);
long nid = MGComposer.mgc.getUniqueId();
sortedTimelineModifiersId.add(nid);
MouseGestureModifier tmp = m.clone(this.mg, nid);
modifiers.put(nid, tmp);
if (m == tocopy.getCurrentModifier()) { currentModifier = tmp; }
}
}
public void reset() {
current = -1;
currentModifier = null;
// status = -1;
}
/*
public void adaptStatus(float t) {
if (sortedTimelineModifiersId.size() == 0 || current >= sortedTimelineModifiersId.size()) {
status = end_of_timeline;
} else {
int tmpMid = current;
if (tmpMid == -1) { tmpMid = 0; }
long tid = sortedTimelineModifiersId.get(tmpMid);
currentModifier = modifiers.get(tid);
if (previewTime(0) > t) {
// not yet far enough to show something...
status = quiet;
currentModifier = null;
} else if (previewTime(0) <= t && previewTime(mg.getDuration()) >= t) {
if (status == quiet) {
status = beginning;
current = tmpMid;
} else {
status = active_gesture;
current = tmpMid;
}
} else if (previewTime(mg.getDuration()) < t) {
// end of the current occurrence is reached
if (tmpMid == sortedTimelineModifiersId.size()-1) {
// nothing after current one
status = end_of_timeline;
current = tmpMid;
current++;
currentModifier = null;
} else {
current = tmpMid;
// does the next one starts directly?
tmpMid++;
tid = sortedTimelineModifiersId.get(tmpMid);
currentModifier = modifiers.get(tid);
if (previewTime(0) <= t && previewTime(mg.getDuration()) >= t) {
status = end_of_gesture_and_beginning;
current = tmpMid;
} else {
status = end_of_gesture;
currentModifier = null;
}
}
}
}
}
public ArrayList<MouseGesturePoint> read(float t) {
ArrayList<MouseGesturePoint> mgps = new ArrayList<MouseGesturePoint>();
if (visible) {
//adaptStatus(t);
if (currentModifier != null) {
}
}
return mgps;
}
*/
public void setModifier() {
if (currentModifier == null) { currentModifier = modifiers.get(sortedTimelineModifiersId.get(0)); }
}
private void sortModifiers() {
sortedTimelineModifiersId.clear();
Iterator iterator = modifiers.keySet().iterator();
while( iterator. hasNext()) {
//System.out.println(iterator.next());
sortedTimelineModifiersId.add((Long) iterator.next());
}
if (sortedTimelineModifiersId.size() > 1) {
Collections.sort(sortedTimelineModifiersId, new MouseGestureModifierComparator(this));
}
}
public void addBlock() {
long modId = MGComposer.mgc.getUniqueId();
MouseGestureModifier mgm = new MouseGestureModifier(mg, modId);
modifiers.put(modId, mgm);
sortModifiers();
}
public void removeBlock(long key) {
modifiers.remove(key);
sortModifiers();
}
public MouseGesture getMg() {
return mg;
}
public void setMg(MouseGesture mg) {
this.mg = mg;
}
public void setFolder(TimelineFolder folder) {
this.folder = folder;
}
public long getId() {
return id;
}
public HashMap<Long, MouseGestureModifier> getModifiers() {
return modifiers;
}
public MouseGestureModifier getCurrentModifier() {
return currentModifier;
}
public boolean isVisible() {
// if (currentModifier != null) { currentModifier = null; }
return visible;
}
public void setVisible(boolean active) {
// if (!active && currentModifier != null) { currentModifier = null; }
this.visible = active;
}
public float previewPointX(int index, float w) {
float val = mg.getMousepoints().get(index).getX();
val += currentModifier.getPointsOffsetX(index);
return previewX(val, w);
}
public float previewX(float val, float w) {
if (currentModifier.getOffsetX() != 0) { val+= currentModifier.getOffsetX(); }
if (currentModifier.isMirrorX()) {
val-= (currentModifier.getOffsetX()*2f);
val = mg.getCenter()[0] - (val-mg.getCenter()[0]);
}
return val*w;
}
public float previewX(float val, int w) { return previewX(val, (float) w); }
public float previewX(float val) { return previewX(val, 1f); }
public float previewPointY(int index, float h) {
float val = mg.getMousepoints().get(index).getY();
val += currentModifier.getPointsOffsetY(index);
return previewY(val, h);
}
public float previewY(float val, float h) {
if (currentModifier.getOffsetY() != 0) { val+= currentModifier.getOffsetY(); }
if (currentModifier.isMirrorY()) {
val-= (currentModifier.getOffsetY()*2f);
val = mg.getCenter()[1] - (val-mg.getCenter()[1]); }
return val*h;
}
public float previewY(float val, int h) { return previewY(val, (float) h); }
public float previewY(float val) { return previewY(val, 1f); }
public float previewSize(float val, int s) {
return val*(float) s;
}
public float previewSize(float val, float s) {
return val*s;
}
public float previewTime(float t) {
if (currentModifier.getScaleT() != 1) {
t*=currentModifier.getScaleT();
}
t+= currentModifier.getOffsetT();
return t;
}
public float previewTime(float t, long key) {
if (modifiers.containsKey(key)) {
if (modifiers.get(key).getScaleT() != 1) {
t*=modifiers.get(key).getScaleT();
}
t+= modifiers.get(key).getOffsetT();
return t;
} else {
return 0;
}
}
public float previewDuration(float t) {
if (currentModifier.getScaleT() != 1) {
t*=currentModifier.getScaleT();
}
return t;
}
public float previewDuration(float t, long key) {
if (modifiers.containsKey(key)) {
if (modifiers.get(key).getScaleT() != 1) {
t*=modifiers.get(key).getScaleT();
}
return t;
} else {
return 0;
}
}
public int getCurrent() {
return current;
}
/*
public int getStatus() {
return status;
}
*/
public ArrayList<Long> getSortedTimelineModifiersId() {
return sortedTimelineModifiersId;
}
/* required by MouseGestureModifierParent */
public MouseGestureModifier getMouseGestureModifierById(long uid) {
if (modifiers.containsKey(uid)) {
return modifiers.get(uid);
} else {
return null;
}
}
public TimelineFolder getFolder() {
return folder;
}
public String getName() {
return name;
}
public int getMode() {
return mode;
}
public void setMode(int mode) {
this.mode = mode;
}
public boolean isInterpolation() {
return interpolation;
}
public void setInterpolation(boolean interpolation) {
this.interpolation = interpolation;
}
public float[] getColor() {
return color;
}
public void setColor(float[] color) {
this.color = color;
}
}