import java.io.*; //import javafx.scene.media.Media; class ScriptNode extends Object3D implements java.io.Serializable { static final long serialVersionUID = -3085403048731698724L; //Mocap mocap; String filename; static class ScriptReader { BufferedReader reader; // parent stuff int totalduration; int duration; int linecount; String line; String lastcommand; String script; boolean waiting; ScriptReader(BufferedReader r, int td, /* int d, int lc, String l,*/ String s) { reader = r; totalduration = td; //duration = d; //linecount = lc; line = ""; // l; //script = s; } } transient ScriptReader reader = null; transient ScriptReader[] readers = null; // recursive scripts transient int stack; //transient String currentscript; //transient String line = null; //transient static SwitchNode speaker = null; static SwitchNode lastspeaker = null; transient SwitchNode myspeaker = null; String scripttext; Object3D owner; ScriptNode(String f) { this.filename = f; name = "Script:" + (String)filename.subSequence(filename.lastIndexOf("/")+1, filename.length()); // filename; //CreateMaterial(); live = true; } ScriptNode(Object3D o) { owner = o; name = "Script:" + o.name; live = true; } Object3D GetRoot() { if (owner == null) return super.GetRoot(); return owner.GetRoot(); } void Init() { if (readers == null) { readers = new ScriptReader[100]; } try { // if (reader != null) // reader.close(); for (int i=readers.length; --i>=0;) { if (readers[i] != null) readers[i].reader.close(); } int totalduration = 0; //int duration = 0; //int linecount = 0; //String line = ""; // if (reader != null) // { // totalduration = reader.totalduration; // duration = reader.duration; // linecount = reader.linecount; // line = reader.line; // } stack = 0; Reader read = null; String scriptname = null; if (filename == null) { scriptname = name; read = new StringReader(scripttext==null?"":scripttext); } else { read = new FileReader(filename); scriptname = filename; } reader = readers[stack] = new ScriptReader(new BufferedReader(read), totalduration, /*duration, linecount, line,*/ scriptname); // String line; // // while ((line = reader.readLine()) != null && ok) { // ok = textToSpeech(line); // } // reader.close(); } catch (Exception e) { e.printStackTrace(); } reader.totalduration = reader.duration = 0; reader.linecount = 0; if (aliases == null) aliases = new java.util.Hashtable(); // aliases.clear(); } void Reset() { Init(); // jan 2014 CameraPane.fullreset = true; } void Step() { //System.err.println(this + " duration = " + reader.duration); if (reader == null) Init(); // if (step == 0) step = STEP; if (CameraPane.AntialiasingEnabled() && CameraPane.ACSIZE != 4) // not to lose totem scene { //if (CameraPane.ACSIZE == 16) step *= 4; step /= CameraPane.ACSIZE; } //if (speakername == null) { // suppose one script CameraPane.STEP = 1; if (CameraPane.FAST) { CameraPane.STEP = reader.duration/step; if (CameraPane.STEP == 0) CameraPane.STEP = 1; if (CameraPane.STEP > 16) // 20) // 100 CameraPane.STEP = 16; // 20; } step *= CameraPane.STEP; // if (duration > step*16 && CameraPane.FAST) // step *= 16; // ? STEP; // else // { // CameraPane.HOLD = true; // } } if (reader.duration > 0) reader.duration -= step; CheckTimers(step); if (reader.duration > 0) { return; } if (reader.waiting) { return; } do { try { reader.line = reader.reader.readLine(); } catch (Exception e) { e.printStackTrace(); } if (reader.line != null) { reader.linecount++; while (reader.line.endsWith(" ")) // problem in SayCommand (and "split") { reader.line = reader.line.substring(0, reader.line.length()-1); } if (reader.line.startsWith(";;")) continue; try { // if (line.startsWith("run")) // { // stack++; // line = line.substring(4, line.length()); // System.err.println("run file: " + line); // reader = readers[stack] = new ScriptReader(new BufferedReader(new FileReader(line)), duration, linecount); // duration = 0; // june 2014 // linecount = 0; // } // if (line.startsWith("return")) // { // assert(readers[stack] == reader); // // reader.reader.close(); // duration = reader.duration; // linecount = reader.linecount; // reader = readers[--stack]; // } if (reader.line.startsWith(";")) { ComputerCommand(); } } catch(Exception e) { e.printStackTrace(); System.err.println(" ******* ERROR IN LAST COMMAND *******"); } // } } } while (reader.line != null && reader.line.startsWith(";") && !reader.waiting); if (reader.waiting) { return; } if (reader.line == null) { // if (CameraPane.LIVE) // Globals.theRenderer.ToggleLive(); // Reset(); // // try // { // line = reader.readLine(); // } catch (Exception e) { // e.printStackTrace(); // } } else { if (reader.line.startsWith("_")) System.err.println(reader.script + " : " + reader.line); else { if (speaker != null) System.err.println(speaker.GetFileRoot().name + " (speaking) : " + reader.line); else System.err.println("no speaker (not a command) : " + reader.line); } } } static java.util.Hashtable aliases; // = new java.util.Hashtable(); static // july 2013 String speakername; static String GetAlias(String s) { while (aliases.get(s) != null) s = aliases.get(s); return s; } Object3D GetObject(String object) { return GetRoot().GetObject(object.split("/"), 0); } void SetLive(String object, boolean live) { object = GetAlias(object); Object3D obj = GetObject(object); if (obj == null) { System.err.println("No object: " + object); return; } obj.live = live; if (!live && obj instanceof SwitchNode) { ((SwitchNode) obj).child = 0; } } void SetMocap(Object3D obj, // String object, String inputname, String begin, String end, boolean force) { // object = GetAlias(object); String iname = GetAlias(inputname); if (!force && iname.equals(inputname)) { // no alias return; } boolean exists = false; while (aliases.get(end) != null) { exists = true; end = GetAlias(end); } int lastframe = 0; if (end.startsWith("s")) // if (exists) { lastframe = end.length() * 120; // seconds } else if (end.startsWith("f")) lastframe = end.length(); // #frames. If "", gives 0 exists = false; while (aliases.get(begin) != null) { exists = true; begin = GetAlias(begin); } int firstframe = 0; if (begin.startsWith("s")) // exists) { firstframe = begin.length() * 120; // seconds } else if (begin.startsWith("f")) firstframe = begin.length(); // frames //Object3D obj = GetObject(object); if (obj instanceof Mocap) { Mocap mocap = (Mocap) obj; if (force || !mocap.fullname.equals(name)) { System.err.println("LoadBVHFile = " + obj + "; name = " + iname + "; first frame = " + firstframe + "; last frame = " + lastframe); obj.blockloop = false; // to force crash right now GetRoot().GetWindow().LoadBVHFile(iname, obj, false, force?firstframe:-1, lastframe); } else { System.err.println(obj + " has same mocap: " + name); } } else { System.err.println(obj + " IS NOT A MOCAP OBJECT"); } } String GetToolTip() { if (reader == null) return name + " (not running)"; String path = ""; for (int i=0; i<=stack; i++) { //path += "/" + Filename(readers[i].script); ScriptReader reader = readers[i]; path += Filename(reader.script) + "; duration=" + reader.duration + "; total=" + reader.totalduration + "; line#" + reader.linecount + ": " + reader.line; if (reader.line != null && // sept 2014 reader.line.startsWith("_")) path += " (" + reader.lastcommand + ")"; path += "\n"; } path += "\n"; for (cTimer t : timers) { path += "timer " + t.delai + " -> "; for (int c=3; c index+2) ((Mocap) object).pinx = Float.parseFloat(strs[index+2]); else { Object3D sourcenode = object.GetFileRoot(); cVector centroid = new cVector(); boolean success = sourcenode.getCentroid(centroid, true); if (!success) new Exception().printStackTrace(); //System.err.println("this = " + sourcenode + ": floor = " + floor.y + ", ground = " + ground); if (sourcenode.parent != null) // && sourcenode.parent.toParent != null) { //LA.xformPos(centroid, sourcenode.parent.toParent, centroid); sourcenode.parent.TransformToWorld(centroid); //, centroid); } ((Mocap) object).pinx = centroid.x; } return; } if (command.equals("pinz")) { if (strs.length > index+2) ((Mocap) object).pinz = Float.parseFloat(strs[index+2]); else { Object3D sourcenode = object.GetFileRoot(); cVector centroid = new cVector(); boolean success = sourcenode.getCentroid(centroid, true); if (!success) new Exception().printStackTrace(); //System.err.println("this = " + sourcenode + ": floor = " + floor.y + ", ground = " + ground); if (sourcenode.parent != null) // && sourcenode.parent.toParent != null) { //LA.xformPos(centroid, sourcenode.parent.toParent, centroid); sourcenode.parent.TransformToWorld(centroid); //, centroid); } ((Mocap) object).pinz = centroid.z; } return; } if (command.equals("gotox")) { if (object.toParent == null) { object.toParent = LA.newMatrix(); object.fromParent = LA.newMatrix(); } object.toParent[3][0] = Float.parseFloat(strs[index+2]); LA.matInvert(object.toParent, object.fromParent); return; } if (command.equals("gotoy")) { if (object.toParent == null) { object.toParent = LA.newMatrix(); object.fromParent = LA.newMatrix(); } object.toParent[3][1] = Float.parseFloat(strs[index+2]); LA.matInvert(object.toParent, object.fromParent); return; } if (command.equals("gotoz")) { if (object.toParent == null) { object.toParent = LA.newMatrix(); object.fromParent = LA.newMatrix(); } object.toParent[3][2] = Float.parseFloat(strs[index+2]); LA.matInvert(object.toParent, object.fromParent); return; } if (command.equals("targetx")) { ((Mocap) object).targetdirx = Float.parseFloat(strs[index+2]); return; } if (command.equals("targetz")) { ((Mocap) object).targetdirz = Float.parseFloat(strs[index+2]); return; } if (command.equals("goalx")) { ((Mocap) object).goalposx = Float.parseFloat(strs[index+2]); return; } if (command.equals("goalz")) { ((Mocap) object).goalposz = Float.parseFloat(strs[index+2]); return; } if (command.equals("fromto")) { cVector from = new cVector(Float.parseFloat(strs[index+2]), 0, // Float.parseFloat(strs[index+3]), Float.parseFloat(strs[index+3])); cVector to = new cVector(Float.parseFloat(strs[index+4]), 0, // Float.parseFloat(strs[index+6]), Float.parseFloat(strs[index+5])); ((Mocap) object).AddFromTo(from, to); return; } // if (command.equals("actionscript")) // { // cVector from = new cVector(Float.parseFloat(strs[index+2]), // Float.parseFloat(strs[index+3]), // Float.parseFloat(strs[index+4])); // //// ScriptNode to = (ScriptNode) GetObject(strs[index+4]); // // ((Mocap) object).AddAction(from, this, strs[index+5]); // return; // } if (command.equals("action")) { cVector from = new cVector(Float.parseFloat(strs[index+2]), Float.parseFloat(strs[index+3]), Float.parseFloat(strs[index+4])); // for (int i=strs.length; --i>=index+6;) // { // // check for aliases first // strs[i] = GetAlias(strs[i]); // } ((Mocap) object).AddAction(from, this, strs, 6); return; } if (command.equals("timer")) { int delai = Integer.parseInt(strs[index+1]); // for (int i=strs.length; --i>=index+6;) // { // // check for aliases first // strs[i] = GetAlias(strs[i]); // } AddTimer(delai, strs); return; } if (command.equals("clearpath")) { ((Mocap) object).ClearPath(); return; } if (command.equals("clearactions")) { ((Mocap) object).ClearActions(); return; } if (command.equals("path")) { ((Mocap) object).SetPath(GetObject(GetAlias(strs[index+2])), this, true); return; } if (command.equals("pathcont")) { ((Mocap) object).SetPath(GetObject(GetAlias(strs[index+2])), this, false); return; } if (command.equals("speaker")) { if (speakername == null || !speakername.equals(strs[index+1])) { //if (mutemocap != null) // && CameraPane.AUTOCAM if (speakername != null && CameraPane.SPEAKERMOCAP) { // switch to neutral mocap String mutemocap = //aliases.get( speakername + "mute"//) ; // while (aliases.get(mutemocap) != null) // mutemocap = aliases.get(mutemocap); String speakermocap = //aliases.get( speakername + "mocap"//) ; String beginmocap = speakername + "mutebegin"; String endmocap = //aliases.get( speakername + "muteend"//) ; if (aliases.get(beginmocap) != null) { beginmocap = GetAlias(beginmocap); } else beginmocap = ""; if (aliases.get(endmocap) != null) { endmocap = GetAlias(endmocap); } else endmocap = ""; System.err.println("speakermocap = " + speakermocap + "; mutemocap = " + mutemocap); SetMocap(GetObject(speakermocap), mutemocap, beginmocap, endmocap, false); } if (speakername != null) { // SetLive(speakername + "righthand", false); // SetLive(speakername + "lefthand", false); // SetLive(speakername + "neck", false); } //} speakername = strs[index+1]; System.err.println("NAME = " + speakername + "; SPEAKERPATH = " + strs[index+1]); // path); System.err.println("OBJECT = " + object + "; SPEAKER = " + speaker); SwitchNode thespeaker = (SwitchNode) object; if (thespeaker != speaker) { lastspeaker = speaker; speaker = thespeaker; } if (speaker != null) speaker.child = 0; myspeaker = speaker; System.err.println("MY SPEAKER = " + myspeaker); if (CameraPane.SPEAKERCAMERA) { String cameraobject = GetAlias(speakername + "camera"); if (cameraobject != null) // && CameraPane.AUTOCAM { // switch to speaker camera Object3D cam = GetObject(cameraobject); boolean success = false; if (cam instanceof Camera) // ? success = Globals.theRenderer.SetCamera((Camera) cam, true); if (success) { CameraPane.ABORTED = true; System.err.println("SET ABORTED (SPEAKERCAMERA) "); } } } if (CameraPane.SPEAKERFOCUS) // rootobject != null) { String rootobject = GetAlias(speakername + "focus"); // switch to speaker camera Object3D root = GetObject(rootobject); System.err.println("ZOOM: root = " + root + "; rootobject = " + rootobject); GetRoot().GetWindow().objEditor.ScreenFit(root, false); CameraPane.trackedobject = root; CameraPane.ABORTED = true; System.err.println("SET ABORTED (SPEAKERFOCUS) "); } // if (talkmocap != null) // && CameraPane.AUTOCAM if (CameraPane.SPEAKERMOCAP) { // switch to talk mocap String talkmocap = aliases.get( speakername + "talk") ; // while (aliases.get(talkmocap) != null) // talkmocap = aliases.get(talkmocap); String speakermocap = aliases.get( speakername + "mocap") ; String beginmocap = speakername + "talkbegin"; String endmocap = //aliases.get( speakername + "talkend"//) ; if (aliases.get(beginmocap) != null) { beginmocap = GetAlias(beginmocap); } else beginmocap = ""; if (aliases.get(endmocap) != null) { endmocap = GetAlias(endmocap); } else endmocap = ""; System.err.println("MOCAP: speakermocap = " + speakermocap + "; talkmocap = " + talkmocap); SetMocap(GetObject(speakermocap), talkmocap, beginmocap, endmocap, false); } SetLive(speakername + "righthand", true); SetLive(speakername + "lefthand", true); SetLive(speakername + "neck", true); } return; } if (command.equals("setpose")) { object.overwriteThis(GetObject(GetAlias(strs[index+2])), Object3D.GEOMETRY); return; } if (command.equals("settransform")) { object.overwriteThis(GetObject(GetAlias(strs[index+2])), Object3D.TRANSFORM); return; } if (command.equals("setsupport")) { boolean random = CameraPane.SWITCH; CameraPane.SWITCH = false; // parse all random nodes if (object.support instanceof Merge) { ((Merge)object.support).renderme(); } object.resetMaster(false); object.linkVerticesThis(null); object.linkVerticesThis(GetObject(GetAlias(strs[index+2]))); // object.setMasterThis(content); // should be identity CameraPane.SWITCH = random; return; } if (command.equals("setchild")) { if (object instanceof SwitchNode) { SwitchNode sw = (SwitchNode) object; int child = Integer.parseInt(strs[index+2]); sw.child = child; sw.Update(); } else new Exception().printStackTrace(); return; } if (command.equals("setcount")) { int c = Integer.parseInt(strs[index+2]); object.transformcount = c; return; } if (command.equals("reset")) { boolean keep = CameraPane.fullreset; CameraPane.fullreset = true; CameraPane.fromscript = true; object.Reset(); CameraPane.fromscript = false; CameraPane.fullreset = keep; return; } if (command.equals("resetall")) { boolean keep = CameraPane.fullreset; CameraPane.fullreset = true; CameraPane.fromscript = true; object.ResetAll(); CameraPane.fromscript = false; CameraPane.fullreset = keep; return; } if (command.equals("rewind")) { //Object3D obj = GetRoot().GetObject(path.split("/"), 0); if (object instanceof Mocap) { Mocap mocap = (Mocap) object; //mocap.SetPositionDelta(false, true, false, true); mocap.Rewind(); mocap.Fade(); } else new Exception().printStackTrace(); return; } if (command.equals("setframe")) // dec 2013 { if (object instanceof Mocap) { Mocap mocap = (Mocap) object; int frame = Integer.parseInt(strs[index+2]); boolean keeplive = mocap.live; mocap.live = true; mocap.setPose(frame); mocap.live = keeplive; // mocap.baseframe = frame; // mocap.frame = frame; } else new Exception().printStackTrace(); return; } if (command.equals("forward")) { // Object3D obj = GetRoot().GetObject(object.split("/"), 0); // // if (obj instanceof Mocap) // { // Mocap mocap = (Mocap) obj; // // String object2 = strs[index+2]; // // int step = Integer.parseInt(object2); // // mocap.baseframe += step; // mocap.frame += step; // } // preparation object.Forward(); return; } if (command.equals("step")) { object.Step(); return; } if (command.equals("flipV")) { object.flipV = true; return; } if (command.equals("unflipV")) { object.flipV = false; return; } if (command.equals("markon")) { if (!object.marked) object.SwitchMark(); //object.marked = true; return; } if (command.equals("markoff")) { if (object.marked) object.SwitchMark(); //object.marked = false; return; } if (command.equals("play")) { object.live = true; return; } if (command.equals("pause")) { object.live = false; return; } if (command.equals("speedon")) { object.speedup = true; return; } if (command.equals("speedoff")) { object.speedup = false; return; } if (command.equals("rewindon")) { object.rewind = true; return; } if (command.equals("rewindoff")) { object.rewind = false; return; } if (command.equals("random")) { object.random = true; return; } if (command.equals("uniform")) { object.random = false; return; } if (command.equals("hide")) { object.hide = true; return; } if (command.equals("show")) { object.hide = false; return; } if (command.equals("skip")) { object.skip = true; return; } if (command.equals("use")) { object.skip = false; return; } if (command.equals("skipmocap") || command.equals("mocapskip")) // oct 2014 { object.skipmocap = true; return; } if (command.equals("usemocap")) { object.skipmocap = false; return; } if (command.equals("dec")) { object.DecCount(); return; } if (command.equals("inc")) { object.IncCount(); return; } if (command.equals("select")) { // TODO assert (GetRoot() == Globals.theRenderer.object); String path = GetAlias(strs[index+1]); GetRoot().GetWindow().Select(GetRoot().GetTreePath(path.split("/"), 0), false, false); return; } if (command.equals("mocap")) { SetMocap(object, // path, strs[index+2], strs.length>index+3?strs[index+3]:"", strs.length>index+4?strs[index+4]:"", true); // String object2 = strs[index+2]; // // if (aliases.get(strs[index+2]) != null) // object2 = aliases.get(strs[index+2]); // // GetRoot().editWindow.LoadBVHFile(object2, GetRoot().GetObject(object.split("/"), 0), false); return; } if (command.equals("sound")) { if (object instanceof Mocap) { Mocap mocap = (Mocap) object; mocap.wav = null; mocap.wavname = GetAlias(strs[index+2]); if (strs.length>index+3) mocap.myvolume = strs[index+3].length(); } return; } if (command.equals("mark")) { if (!object.marked) object.SwitchMark(); //object.marked = true; return; } if (command.equals("unmark")) { if (object.marked) object.SwitchMark(); //object.marked = false; return; } if (command.equals("support")) { object.link2master = true; return; } if (command.equals("unsupport")) { object.link2master = false; return; } if (command.equals("resettransform")) { if (object.toParent != null) { LA.matIdentity(object.toParent); LA.matIdentity(object.fromParent); } return; } if (command.equals("resetrotation")) { if (object.toParent != null) { LA.matIdentity(object.toParent, true); LA.matIdentity(object.fromParent, true); } return; } if (command.equals("resettranslation")) { if (object.toParent != null) { LA.matIdentity(object.toParent, false); LA.matIdentity(object.fromParent, false); } return; } if (command.equals("repairparent")) { for (int i=0; i timers = new java.util.Vector(); void AddTimer(int delai, String[] command) { if (timers == null) timers = new java.util.Vector(); timers.add(new cTimer(delai, command)); } void CheckTimers(int step) { java.util.Vector toremove = new java.util.Vector(); if (timers == null) timers = new java.util.Vector(); for (cTimer t : timers) { t.delai -= step; if (t.delai <= 0) { System.err.print("timer command (" + this + ") :"); for (int c=3; c(); timers.clear(); } /* 1IY.obj 2IH.obj 3EH.obj 4AA.obj 5OW.obj 6UW.obj 7ER.obj 8S.obj 9SH.obj 10F.obj 11TH.obj 12M.obj 13T.obj 14L.obj 15W.obj 16K.obj */ int GetPhoneme(String s) { if (s.equals("_")) return 0; if (s.equals("i") || s.equals("h") || s.equals("g") || s.equals("N")) return 1; if (s.equals("I") || s.equals("j")) return 2; if (s.equals("AI")) return 4; if (s.equals("E") || s.equals("EI")) return 3; if (s.equals("A") || s.equals("O") || s.equals("{") || s.equals("V") || s.equals("aU") || s.equals("OI") /*new */) return 4; if (s.equals("@U")) return 5; if (s.equals("u")) return 6; if (s.equals("@") || s.equals("r") || s.equals("r=")) return 7; if (s.equals("s") || s.equals("z")) return 8; if (s.equals("S") || s.equals("Z") || s.equals("tS")) return 9; if (s.equals("f") || s.equals("v")) return 10; if (s.equals("D") || s.equals("T") || s.equals("n")) return 11; if (s.equals("m") || s.equals("b") || s.equals("p")) return 12; if (s.equals("d") || s.equals("t")) // || s.equals("n")) return 13; if (s.equals("l")) return 14; if (s.equals("w") || s.equals("U")) return 15; if (s.equals("k")) return 16; System.err.println("PHONEME NOT FOUND : " + s); return 0; } void ExecCommand() { //System.out.println("Command = " + line + "; duration = " + duration); if (false) // line.startsWith(";")) { assert(reader.duration == 0); // ComputerCommand(); // Step(); // skip "sleep" phoneme corresponding to one frame duration (9 ms) } else { //if (speaker != null) { // phoneme String[] strs = reader.line.split(" ", 3); // if (strs[0].length() > 0 && !strs[0].equals("#")) { // System.out.print(strs[0]); if (myspeaker != null) myspeaker.child = GetPhoneme(strs[0]); // Integer.parseInt(strs[0]); if (reader.duration == 0 && strs.length > 1) { CameraPane.HOLD = false; reader.duration = Integer.parseInt(strs[1]); if (reader.duration % STEP != 0) { // System.err.println("Warning duration not STEP*x = " + duration); reader.duration /= STEP; reader.duration *= STEP; } //System.err.println("DURATION = " + duration); reader.totalduration += reader.duration; } //else duration = 0; } // else // System.out.println(); } } } int step = 8; // ms static int STEP = 8; // or 9 for old totem scene // to be removed... //transient int duration = 0; //transient int totalduration = 0; //transient int linecount = 0; //transient boolean waiting; void RunCommand() { if (reader.waiting) return; if (reader.line == null) // || duration == 0) Step(); if (reader.line != null) ExecCommand(); } boolean isLive() { if (scripttext != null) return true; return live; } void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) { if (CameraPane.ABORTED) { System.out.println("SKIP node: " + this); return; } if (isLive() && Globals.isLIVE() && display.DrawMode() == display.SHADOW) { if (reader == null) Init(); Step(); try { RunCommand(); } catch (Exception e) { e.printStackTrace(); System.err.println(" ******* ERROR IN COMMAND WHILE DRAWING *******"); } } // RunCommand(); // super.DrawNode(display, root, selected); } Object3D deepCopy() { ScriptNode e = new ScriptNode(filename); deepCopySelf(e); return e; } protected void deepCopyNode(Object3D other) { super.deepCopyNode(other); // FrameSelector bp = (FrameSelector)other; // bp.frame = (int)(Math.random()*(getNumFrames() - mocap.offset)); } // void createEditWindow(GroupEditor callee, boolean newWindow) // { // //editWindow = (new SphereEditor(this, deepCopy(), callee)).GetEditor(); // if (newWindow) // { // objectUI = new FrameEditor(this, deepCopy(), callee); // } else // { // objectUI = new FrameEditor(this, callee); // } // editWindow = objectUI.GetEditor(); // } // // int frame; }