//public List<string> removedSelectedGIDs; IEnumerator Start() { this.model = new ChainXModel(); this.model.SetController(this); GameObject anObj = this.CreateVoxel(0, Const.UI_SELECTING_VOXEL_NAME, Vector3.zero); anObj.transform.SetParent(GameObject.Find(Const.PAINT_TOOL_PATH).transform); anObj.GetComponent <Renderer>().enabled = false; anObj.layer = Const.UI_LAYER; this.paintTool = GameObject.Find(Const.PAINT_TOOL_PATH + Const.UI_SELECTING_POINTER_NAME); this.paintTool.layer = Const.UI_LAYER; this.screenSize.width = Screen.width; this.screenSize.height = Screen.height; this.SetPositionOfPaintTool(); this.debuggerObj = GameObject.Find("DebugLog/Viewport/Content"); this.cv = new ChainVoxel(this); this.selectedObjects = new List <GameObject> (); //this.removedSelectedGIDs = new List<string> (); this.socket = new EmulatedWebSocket(this); StartCoroutine(this.socket.Connect()); //Util.START_NANO_TIME = System.DateTime.Now.Ticks; //タイムスタンプ開始 yield return(this.socket.Listen()); }
void Update() { //Debug.Log(DateTime.UtcNow.Ticks); lock (ChainXController.thisLock) { this.UpdateVoxels(); //this.SetUpGUICompornets (); //スクリーンサイズが変更された時、実行される if (this.screenSize.width != Screen.width || this.screenSize.height != Screen.height) { this.SetPositionOfPaintTool(); this.screenSize.width = Screen.width; this.screenSize.height = Screen.height; } //マウスクリックの際の処理 if (Input.GetMouseButtonDown(Const.MOUSE_LEFT_CLICK)) { if (Input.GetKey(KeyCode.LeftAlt)) { //Do nothing for Orbit, Zoom, etc.. } else if (this.clickUI()) { this.cleanSelectedObjects(); //Voxelの選択解除 } else if (this.paintTool.name == Const.UI_SELECTING_POINTER_NAME) { this.clickVoxel(); //マウスクリックしてオブジェクトを選択する } else { //VoxelまたはVoxelsが選択中のとき this.paintVoxels(); //VoxelまたはVoxelsをペイントする } } //キーボード操作(移動、グループ作成、解除、削除) Operation o = null; if (this.selectedObjects.Count > 0) { //3. MOVEの移動方向を追加 Vector3 arrowV = Vector3.zero; if (Input.GetKeyUp(KeyCode.UpArrow)) { arrowV = new Vector3(1, 0, 0); } else if (Input.GetKeyUp(KeyCode.DownArrow)) { arrowV = new Vector3(-1, 0, 0); } else if (Input.GetKeyUp(KeyCode.RightArrow)) { arrowV = new Vector3(0, 0, -1); } else if (Input.GetKeyUp(KeyCode.LeftArrow)) { arrowV = new Vector3(0, 0, 1); } else if (Input.GetKeyUp(KeyCode.K)) { arrowV = new Vector3(0, 1, 0); } else if (Input.GetKeyUp(KeyCode.J)) { arrowV = new Vector3(0, -1, 0); } if (arrowV == Vector3.zero) { if (Input.GetKeyUp(KeyCode.D)) { // // VoxelまたはGroupVoxelを削除する // if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.LeftCommand) || Input.GetKey(KeyCode.RightControl) || Input.GetKey(KeyCode.RightCommand)) { List <Operation> deleteOps = this.model.CreateDeleteOperation(this.selectedObjects); foreach (Operation op in deleteOps) { this.ApplyChainVoxel(op); } } } else if (Input.GetKeyDown(KeyCode.G)) { // // グループの参加、離脱 // グループの中にグループは、今は処理しない! // string gid; if (this.selectedObjects.Count == 1) { if (this.selectedObjects [0].transform.childCount > 0) { //選択したオブジェクトが一つで、それがグループである場合、グループを解除 gid = this.selectedObjects [0].transform.root.name; o = new Operation(this.socket.getID(), Operation.LEAVE_ALL, "{\"posIDs\": \"" + this.model.getPosIDsFromObj(this.selectedObjects[0]) + "\", \"gid\": \"" + gid + "\"}"); this.ApplyChainVoxel(o); } else { } //何もしない } else { gid = ChainXModel.CreateGID(); o = new Operation(this.socket.getID(), Operation.JOIN_ALL, "{\"posIDs\": \"" + this.model.getPosIDsFromObjects(this.selectedObjects) + "\", \"gid\": \"" + gid + "\"}"); this.ApplyChainVoxel(o); } } } else { /* * foreach (GameObject anObj in this.selectedObjects) { * Debug.Log (anObj.name); * } */ //Debug.Log("MOVE"); this.selectedObjects = Util.ArrangeGameObjects(this.selectedObjects, arrowV); List <Operation> moveOps = this.model.CreateMoveOperations(this.selectedObjects, arrowV); foreach (Operation moveOp in moveOps) { this.ApplyChainVoxel(moveOp); } } } if (o != null) { //this.cv.show(); //this.cv.stt.show(); } } }
/* * PaintToolのVoxelまたはグループVoxelが選択されていて、マウスクリックされたときに呼ばれる。 * ペイントさせ方は、ぶつかったオブジェクト(Plane)よりも手前のオブジェクトを * 「後ろ側から手前に」辿っていき、Voxelを挿入する。 */ private void paintVoxels() { string paintToolName = this.model.getCurrentPaintTool(); List <Operation> ops = new List <Operation>(); Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit = new RaycastHit(); if (Physics.Raycast(ray, out hit)) { if (paintToolName.IndexOf(ChainXModel.PAINT_TOOL_VOXEL_ID) > -1) { // //単位Voxelをペイントする // float distance = hit.distance - 0.5f; //ヒットしたRayより少し手前のPointをたどる Vector3 hitPointShort = ChainXModel.GetRoundIntPoint(ray.GetPoint(distance)); int textureType = int.Parse(this.paintTool.GetComponent <Text>().text); ops.Add(new Operation(this.socket.getID(), Operation.INSERT, "{\"posID\": \"" + ChainXModel.CreatePosID(hitPointShort) + "\", \"textureType\":\"" + textureType + "\"}" )); } else if (paintToolName.IndexOf(ChainXModel.PAINT_TOOL_GROUP_ID) > -1) { // //グループVoxelsをペイントする // float cursor_d = hit.distance - 0.5f; Vector3 hitPointShort = ChainXModel.GetRoundIntPoint(ray.GetPoint(cursor_d)); //もっともヒットポイントに近いオブジェクトをグループVoxelsの中から見つける GameObject closeObjToHitPoint = null; float minDistance = float.MaxValue; GameObject groupObj = GameObject.Find(paintToolName); foreach (Transform aPart in groupObj.transform) { float d = Vector3.Distance(aPart.gameObject.transform.position, hitPointShort); if (d < minDistance) { minDistance = d; closeObjToHitPoint = aPart.gameObject; } } bool put_enable; Vector3 diffV = Vector3.zero; string posIDs = ""; string textureTypes = ""; while (cursor_d > 0) { posIDs = ""; textureTypes = ""; hitPointShort = ChainXModel.GetRoundIntPoint(ray.GetPoint(cursor_d)); diffV = hitPointShort - closeObjToHitPoint.transform.position; put_enable = true; foreach (Transform aPart in groupObj.transform) { Vector3 movingV = aPart.gameObject.transform.position + diffV; if (GameObject.Find(Util.CreatePosID(movingV)) != null) { put_enable = false; break; } posIDs += Util.CreatePosID(movingV) + Const.SPLIT_CHAR; textureTypes += aPart.gameObject.GetComponent <Text>().text + Const.SPLIT_CHAR; } if (put_enable) { break; } cursor_d--; } posIDs = posIDs.TrimEnd(Const.SPLIT_CHAR); textureTypes = textureTypes.TrimEnd(Const.SPLIT_CHAR); this.selectedObjects.Remove(groupObj); string gid = ChainXModel.CreateGID(); ops.Add(new Operation(this.socket.getID(), Operation.INSERT_ALL, "{\"posIDs\": \"" + posIDs + "\", \"gid\": \"" + gid + "\", \"textureTypes\":\"" + textureTypes + "\"}") ); ops.Add(new Operation(this.socket.getID(), Operation.JOIN_ALL, "{\"posIDs\": \"" + posIDs + "\", \"gid\": \"" + gid + "\"}") ); } long ts = ops[0].getTimestamp(); for (int i = 0; i < ops.Count; i++) { ops[i].setTimestamp(ts + i); //できる限り1に近づけないと間に入り込まれる this.ApplyChainVoxel(ops[i]); } //Debug.DrawLine(ray.origin, hitPointShort, Color.red, 60.0f, true); //レーザービーム } }
public static void Test() { ChainXModel model = new ChainXModel(); /* * グループボクセルの中心座標を求める */ GameObject aParent = new GameObject("P"); GameObject[] children = new GameObject[5]; for (int i = 0; i < children.Length; ++i) { children[i] = GameObject.CreatePrimitive(PrimitiveType.Cube); children[i].SetActive(true); children[i].name = "c" + i.ToString(); children[i].transform.SetParent(aParent.transform); } //パターン1 children[0].transform.position = new Vector3(0, 0, 0); children[1].transform.position = new Vector3(0, 1, 0); children[2].transform.position = new Vector3(0, 2, 0); children[3].transform.position = new Vector3(0, 2, 1); children[4].transform.position = new Vector3(1, 2, 0); Vector3 a, b; model.GetMaxMinPositions(aParent, out a, out b); Debug.Assert(a == new Vector3(1, 2, 1)); Debug.Assert(b == new Vector3(0, 0, 0)); Vector3 res = model.GetBottomCenterPosition(aParent, 0.0f); Debug.Assert(res == new Vector3(0.5f, 0, 0.5f)); //パターン2 children[0].transform.position = new Vector3(5, 5, 5); children[1].transform.position = new Vector3(5, 5, 6); children[2].transform.position = new Vector3(6, 5, 5); children[3].transform.position = new Vector3(5, 0, 5); children[4].transform.position = new Vector3(5, 5, 8); model.GetMaxMinPositions(aParent, out a, out b); Debug.Assert(a == new Vector3(6, 5, 8)); Debug.Assert(b == new Vector3(5, 0, 5)); res = model.GetBottomCenterPosition(aParent, 0.0f); Debug.Assert(res == new Vector3(5.5f, 0, 6.5f)); //パターン3 children[0].transform.position = new Vector3(-2, 0, 0); children[1].transform.position = new Vector3(-1, 1, 0); children[2].transform.position = new Vector3(-2, 2, 0); children[3].transform.position = new Vector3(-2, 3, 0); children[4].transform.position = new Vector3(-2, 4, 0); model.GetMaxMinPositions(aParent, out a, out b); Debug.Assert(a == new Vector3(-1, 4, 0)); Debug.Assert(b == new Vector3(-2, 0, 0)); res = model.GetBottomCenterPosition(aParent, 0.0f); Debug.Assert(res == new Vector3(-1.5f, 0, 0)); //GameObject.Destroy(aParent); //ここで作成した可視化をしないようにしている /* * Tests for PaintTool */ model.getPaintTool(0, 1); Debug.Assert(model.getPaintTool(0, 0) == "voxel0"); Debug.Assert(model.getPaintTool(1, 0) == "voxel1"); Debug.Assert(model.getPaintTool(1, 0) == "voxel2"); Debug.Assert(model.getPaintTool(-1, 0) == "voxel1"); Debug.Assert(model.getPaintTool(-1, 0) == "voxel0"); Debug.Assert(model.getPaintTool(-1, 0) == "voxel7"); Debug.Assert(model.getPaintTool(0, 1) == "pointer"); model.AddGroupToUI("group1"); Debug.Assert(model.getPaintTool(0, 1) == "voxel0"); Debug.Assert(model.getPaintTool(0, 1) == "group1"); model.AddGroupToUI("group1"); Debug.Assert(model.getPaintTool(1, 0) == "group1"); model.RemoveGroupFromUI("group1"); Debug.Assert(model.getCurrentPaintTool() == "pointer"); Debug.Assert(model.getPaintTool(-1, 0) == "pointer"); Debug.Assert(model.getPaintTool(-1, 0) == "pointer"); Debug.Log("End a ChainXModel class test"); }
/* * */ public List <Operation> CreateMoveOperations(List <GameObject> objects, Vector3 transMatrix) { List <Operation> operations = new List <Operation>(); foreach (GameObject anObj in objects) { if (anObj.transform.childCount > 0) { // //When selecting multiple voxels or polygon // if (anObj.transform.childCount == 1) { //When selecting polygon /* * foreach (Transform child in anObj.transform) { * string[] posIDs = ObjLoadHelper.GetEmptyVoxels(child.gameObject); * //Debug.Log ("posID(emptyVoxel)" + posIDs [posIDs.Length-1]); * operations.Add (new Operation (this.controller.socket.getID(), Operation.MOVE_POLYGON, "{\"gid\": \"" + anObj.name + * "\", \"posIDs\": \"" + Util.GetCommaLineFrom (posIDs) + * "\", \"transMatrix\": \"" + ChainXModel.CreatePosID (transMatrix) + "\"}") * ); * } */ } else { //When selecting multiple voxels List <string> posIDs = new List <string> (); List <string> destPosIDs = new List <string> (); List <string> destTextureTypes = new List <string> (); foreach (Transform child in anObj.transform) { //Debug.Assert (Util.CreatePosID (child.position) == child.name); Vector3 destPosition = Util.SplitPosID(child.name) + transMatrix; posIDs.Add(child.name); destPosIDs.Add(Util.CreatePosID(destPosition)); Voxel aVoxel = this.controller.cv.getVoxel(child.name); destTextureTypes.Add(aVoxel.getTextureType().ToString()); } string posIDsLine = Util.GetCommaLineFrom(posIDs); string destPosIDsLine = Util.GetCommaLineFrom(destPosIDs); Operation[] ops = new Operation[4]; ops[0] = new Operation( this.controller.socket.getID(), Operation.LEAVE_ALL, "{\"gid\": \"" + anObj.name + "\", \"posIDs\": \"" + posIDsLine + "\"}" ); ops[1] = new Operation( this.controller.socket.getID(), Operation.DELETE_ALL, "{\"gid\": \"" + anObj.name + "\", \"posIDs\": \"" + posIDsLine + "\"}" ); ops[2] = new Operation( this.controller.socket.getID(), Operation.INSERT_ALL, "{\"gid\": \"" + anObj.name + "\", \"textureTypes\": \"" + Util.GetCommaLineFrom(destTextureTypes) + "\", \"posIDs\": \"" + destPosIDsLine + "\"}" ); ops[3] = new Operation( this.controller.socket.getID(), Operation.JOIN_ALL, "{\"gid\": \"" + anObj.name + "\", \"posIDs\": \"" + destPosIDsLine + "\"}" ); long ts = ops[0].getTimestamp(); for (int i = 0; i < ops.Length; i++) { ops[i].setTimestamp(ts + i); //できる限り1に近づけないと間に入り込まれる operations.Add(ops[i]); } } } else { //Debug.Log (anObj.name); //Debug.Log (anObj.transform.childCount); operations.Add(new Operation( this.controller.socket.getID(), Operation.MOVE, "{\"posID\": \"" + anObj.name + "\", \"transMatrix\": \"" + ChainXModel.CreatePosID(transMatrix) + "\"}") ); } } return(operations); }
public IEnumerator Listen() { //this.SendBinary(-1, Const.START_BINARY_HEADER); byte[] msgBinary = null; string[] filepaths = { "", "" }; while (true) { msgBinary = this.ws.Recv(); if (msgBinary != null) { //Debug.Log (Encoding.ASCII.GetString(msgBinary)); //byte[] idBinary = this.getIdFromEndUntilAt(ref receivedBinary); //int destID = System.BitConverter.ToInt32(idBinary, 0); //送り先!! //byte[] msgBinary = this.getOperationFromEndUntilAt(ref receivedBinary); if (this.partEqual(ref msgBinary, ref Const.OPERATION_BINARY_HEADER)) { string line = Encoding.UTF8.GetString(msgBinary); line = line.Remove(0, Const.OPERATION_HEADER.Length).Trim(); Operation op = Operation.FromJson(line); this.controller.cv.apply(op, ChainVoxel.REMOTE_OPERATION); } else if (this.partEqual(ref msgBinary, ref Const.JOIN_BINARY_HEADER)) { string msg = Encoding.UTF8.GetString(msgBinary); msg = msg.Replace(Const.JOIN_HEADER, ""); int intID = int.Parse(msg); if (!this.siteIDs.Contains(intID)) { this.siteIDs.Add(intID); } //foreach (int sid in this.siteIDs) { Debug.Log("sid: " + sid); } //Debug.Log("this.id:" + this.id); //Debug.Log("joined id:" + intID); } else if (this.partEqual(ref msgBinary, ref Const.ID_LIST_BINARY_HEADER)) { string msg = Encoding.UTF8.GetString(msgBinary); int atIndex = msg.IndexOf(Const.MSG_SPLIT_CHAR); string idsLine = msg.Substring(atIndex + 1); //atIndex+1から最後まで String[] strIDs = idsLine.Split(Const.SPLIT_CHAR); foreach (string strID in strIDs) { int intID = int.Parse(strID); if (!this.siteIDs.Contains(intID)) { this.siteIDs.Add(intID); } } this.leaderID = this.siteIDs[0]; this.id = this.siteIDs[this.siteIDs.Count - 1]; } else if (this.partEqual(ref msgBinary, ref Const.SOME_FILE_BINARY_HEADER)) { string filepath = this.getPathUntilAt(ref msgBinary); int start_i = Const.SOME_FILE_HEADER.Length + filepath.Length + 1; //1='@' string path = Application.persistentDataPath + "/" + filepath; FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write); fs.Write(msgBinary, start_i, msgBinary.Length - start_i); fs.Close(); if (Path.GetExtension(path) == ".txt") { //Debug.Log (path); this.controller.cv.LoadSavedData(path); } else if (Path.GetExtension(path) == ".obj") { filepaths[0] = path; } else if (Path.GetExtension(path) == ".jpg") { filepaths[1] = path; } if (filepaths[0] != "" && filepaths[1] != "") { // // When all dependent files of a 3d obj have been collected, // Build the 3d obj. // string[] posIDs = ObjLoadHelper.LoadObj(filepaths, new Vector3(0, 5, 0)); //string[] posIDs = ObjLoadHelper.LoadOnlyObj(filepaths[0], new Vector3 (0,5,0)); Operation op = new Operation(0, Operation.INSERT_POLYGON, "{\"posIDs\": \"" + Util.GetCommaLineFrom(posIDs) + "\", \"gid\": \"" + ChainXModel.CreateGID() + "\", \"objPath\":\"" + filepaths[0] + "\"}"); //Debug.Log(Operation.ToJson(op)); this.controller.cv.apply(op, ChainVoxel.LOCAL_OPERATION); filepaths = new string[] { "", "" }; //Clear for the next 3d objs } } } if (this.ws.error != null) { Debug.LogError("Error: " + this.ws.error); break; } yield return(0); } this.ws.Close(); }
/** * Test an Operation class */ public static void Test() { int numberOfTest = Const.TEST_QUALITY; // // A test for Operation.CombinePosition(). // for (int t = 0; t < numberOfTest; ++t) { Vector3 posIDVector = Util.CreateRandomVector3(-10000, 10000); Vector3 transMatrixVector = Util.CreateRandomTransMatrix(); Debug.Assert( ChainXModel.CreatePosID(posIDVector + transMatrixVector) == Operation.CombinePosition( ChainXModel.CreatePosID(posIDVector), ChainXModel.CreatePosID(transMatrixVector) ) ); } // // Jsonへの変換とその逆ができているかをチェック // Operationへの初期値の値の変化がないかをチェック at CreateRandomOperation() // string json = ""; Operation o1, o2; for (int t = 0; t < numberOfTest; ++t) { o1 = Operation.CreateRandomOperation(); json = Operation.ToJson(o1); o2 = Operation.FromJson(json); Debug.Assert(o1.getSID() == o2.getSID()); Debug.Assert(o1.getOpType() == o2.getOpType()); Debug.Assert(o1.getTimestamp() == o2.getTimestamp()); switch (o1.getOpType()) { case Operation.INSERT: Debug.Assert(o1.getPosID() == o2.getPosID()); Debug.Assert(o1.getTextureType() == o2.getTextureType()); break; case Operation.DELETE: Debug.Assert(o1.getPosID() == o2.getPosID()); break; case Operation.MOVE: Debug.Assert(o1.getPosID() == o2.getPosID()); Debug.Assert(o1.getTransMatrix() == o2.getTransMatrix()); Debug.Assert(o1.getDestPosID() == o2.getDestPosID()); break; case Operation.CREATE: Debug.Assert(o1.getGID() == o2.getGID()); break; case Operation.JOIN: case Operation.LEAVE: Debug.Assert(o1.getGID() == o2.getGID()); Debug.Assert(o1.getPosID() == o2.getPosID()); break; case Operation.JOIN_ALL: case Operation.LEAVE_ALL: Debug.Assert(o1.getGID() == o2.getGID()); Debug.Assert(Util.GetCommaLineFrom(o1.getPosIDs()) == Util.GetCommaLineFrom(o2.getPosIDs())); break; case Operation.MOVE_ALL: Debug.Assert(Util.GetCommaLineFrom(o1.getPosIDs()) == Util.GetCommaLineFrom(o2.getPosIDs())); Debug.Assert(o1.getTransMatrix() == o2.getTransMatrix()); Debug.Assert(Util.GetCommaLineFrom(o1.getDestPosIDs()) == Util.GetCommaLineFrom(o2.getDestPosIDs())); Debug.Assert(o1.getGID() == o2.getGID()); break; case Operation.INSERT_ALL: Debug.Assert(Util.GetCommaLineFrom(o1.getPosIDs()) == Util.GetCommaLineFrom(o2.getPosIDs())); Debug.Assert(o1.getTextureType() == o2.getTextureType()); Debug.Assert(o1.getGID() == o2.getGID()); break; case Operation.DELETE_ALL: Debug.Assert(Util.GetCommaLineFrom(o1.getPosIDs()) == Util.GetCommaLineFrom(o2.getPosIDs())); Debug.Assert(o1.getGID() == o2.getGID()); break; case Operation.INSERT_POLYGON: Debug.Assert(Util.GetCommaLineFrom(o1.getPosIDs()) == Util.GetCommaLineFrom(o2.getPosIDs())); Debug.Assert(o1.getObjPath() == o2.getObjPath()); Debug.Assert(o1.getGID() == o2.getGID()); break; case Operation.DELETE_POLYGON: Debug.Assert(Util.GetCommaLineFrom(o1.getPosIDs()) == Util.GetCommaLineFrom(o2.getPosIDs())); Debug.Assert(o1.getGID() == o2.getGID()); break; case Operation.MOVE_POLYGON: Debug.Assert(Util.GetCommaLineFrom(o1.getPosIDs()) == Util.GetCommaLineFrom(o2.getPosIDs())); Debug.Assert(o1.getTransMatrix() == o2.getTransMatrix()); Debug.Assert(Util.GetCommaLineFrom(o1.getDestPosIDs()) == Util.GetCommaLineFrom(o2.getDestPosIDs())); Debug.Assert(o1.getGID() == o2.getGID()); break; default: throw new System.InvalidOperationException( String.Format("Operation{0} at CreateRandomOperation()", o1.getOpType()) ); } } Debug.Log("End an Operation class test"); }