public void DeleteBox(NPVoxBone bone, NPVoxBox box) { Undo.RecordObject(this, "Delete Box"); List <NPVoxBox> boxes = GetBoxes(bone); boxes.Remove(box); }
public override void Initialize(NPVoxCoord size) { base.Initialize(size); boneMasks = new uint[size.X * size.Y * size.Z]; RootBone = new NPVoxBone("Root", 0, null); AllBones = new NPVoxBone[] { }; }
public void SetBoneMask(uint mask, bool includingDescendants) { NPVoxBoneModel transformedModel = CurrentModelFactory.GetProduct() as NPVoxBoneModel; NPVoxBone[] allBones = ((NPVoxBoneModel)transformedModel).AllBones; SetBoneMask(includingDescendants ? NPVoxBone.GetMaskWithDescendants(ref allBones, mask) : mask); }
public NPVoxBox AddBox(NPVoxBone bone) { Undo.RecordObject(this, "Add Box"); List <NPVoxBox> boxes = GetBoxes(bone); boxes.Add(new NPVoxBox(NPVoxCoordUtil.ToCoord(bone.Anchor), NPVoxCoordUtil.ToCoord(bone.Anchor) + NPVoxCoord.ONE)); return(boxes[boxes.Count - 1]); }
// =================================================================================================== // Tools // =================================================================================================== public void RecenterBonePivot(NPVoxBoneModel model) { NPVoxBone[] bones = NPVoxBone.GetRootBones(ref model.AllBones, NPVoxBone.GetBonesInMask(ref model.AllBones, boneMask)); if (bones.Length == 1) { Vector3 pivotOrigin = GetAffectedBox().SaveCenter; Vector3 pivotForSingleBone = model.GetAffectedArea(1u << (bones[0].ID - 1)).SaveCenter; PivotOffset = pivotForSingleBone - pivotOrigin; } }
public override void CopyOver(NPVoxModel source) { base.CopyOver(source); if (source is NPVoxBoneModel) { NPVoxBoneModel boneModel = (source as NPVoxBoneModel); boneMasks = (uint[])boneModel.boneMasks.Clone(); this.AllBones = NPVoxBone.CloneBones(boneModel.AllBones); } }
public List <NPVoxBox> GetBoxes(NPVoxBone bone) { if (bone.ID == 0) { return(new List <NPVoxBox>()); } List <NPVoxBox> boxes = this.AllBoxes[bone.ID - 1].Boxes; if (boxes == null) { boxes = this.AllBoxes[bone.ID - 1].Boxes = new List <NPVoxBox>(); } return(boxes); }
public NPVoxBone(string name, int id, NPVoxBone parent) { Name = name; ID = id; if (parent != null) { ParentID = parent.ID; Mask = parent.Mask | (1u << (id - 1)); } else { Mask = ID != 0 ? (1u << (id - 1)) : 0; ParentID = 0; } }
public static bool IsDescendant(ref NPVoxBone[] allBones, NPVoxBone parent, NPVoxBone descendant) { if (descendant.ParentID == parent.ID) { return(true); } else if (descendant.ParentID == 0) { return(false); } else { return(IsDescendant(ref allBones, parent, GetBoneByID(ref allBones, descendant.ParentID))); } }
public NPVoxBone AddBone(NPVoxBone parent) { Undo.RecordObject(this, "Add Bone"); NPVoxBone child = NPVoxBone.AddBone(ref AllBones, parent); if (child != null) { child.Name = parent.Name; if (Input != null) { NPVoxModel model = ((NPVoxIModelFactory)Input).GetProduct(); child.Anchor = model.BoundingBox.SaveCenter; } return(child); } return(null); }
public void ToggleBoneMask(uint mask, bool includingDescendants) { NPVoxSkeletonTransformer t = ((NPVoxSkeletonTransformer)SelectedTransformer); NPVoxBoneModel transformedModel = CurrentModelFactory.GetProduct() as NPVoxBoneModel; NPVoxBone[] allBones = ((NPVoxBoneModel)transformedModel).AllBones; uint toggleMask = includingDescendants ? NPVoxBone.GetMaskWithDescendants(ref allBones, mask) : mask; if ((mask & t.BoneMask) != 0) { SetBoneMask(t.BoneMask & ~toggleMask); } else { SetBoneMask(t.BoneMask | toggleMask); } }
public static NPVoxBone[] CloneBones(NPVoxBone[] allBones) { NPVoxBone[] bones = new NPVoxBone[allBones.Length]; for (int i = 0; i < allBones.Length; i++) { if (allBones[i] != null && allBones[i].ID > 0) { NPVoxBone sourceBone = allBones[i]; UnityEngine.Assertions.Assert.AreEqual(i, sourceBone.ID - 1); bones[i] = new NPVoxBone(sourceBone.Name, sourceBone.ID, sourceBone.ParentID > 0 ? bones[sourceBone.ParentID - 1] : null); bones[i].Anchor = sourceBone.Anchor; bones[i].EulerAngles = sourceBone.EulerAngles; } } return(bones); }
// =================================================================================================== // Name // =================================================================================================== protected void RegenerateName(NPVoxBoneModel model) { if (regenerateName) { regenerateName = false; NPVoxBone[] bones = NPVoxBone.GetRootBones(ref model.AllBones, NPVoxBone.GetBonesInMask(ref model.AllBones, boneMask)); string name = ""; foreach (NPVoxBone bone in bones) { if (!string.IsNullOrEmpty(name)) { name += ", "; } name += bone.Name; } this.InstanceName = name; } }
public static NPVoxBone AddBone(ref NPVoxBone[] allBones, NPVoxBone parent) { int nextBoneID = GetNextBoneID(allBones, parent.ID); if (nextBoneID < 0) { return(null); } NPVoxBone newBone = new NPVoxBone("new", nextBoneID, parent); if (allBones.Length > nextBoneID - 1) { allBones[nextBoneID - 1] = newBone; } else { UnityEditor.ArrayUtility.Add(ref allBones, newBone); } return(newBone); }
public System.Func <NPVoxISceneEditable, bool> DrawSceneTool(NPVoxToUnity npVoxToUnity, UnityEngine.Transform transform, int tool) { // offset if (CurrentEditedBone == null) { return(null); } NPVoxBoneModel boneModel = GetProduct() as NPVoxBoneModel; if (boneModel == null) { return(null); } if (lastMask != 1u << (CurrentEditedBone.ID - 1)) { lastMask = 1u << (CurrentEditedBone.ID - 1); currentPivot = npVoxToUnity.ToUnityPosition(boneModel.GetAffectedArea(lastMask).SaveCenter); } Vector3 offset = npVoxToUnity.ToUnityDirection(CurrentEditedBone.Anchor); if (tool == 0) { offset = npVoxToUnity.ToSaveVoxDirection(Handles.PositionHandle(currentPivot + offset, Quaternion.identity) - currentPivot); if (offset != CurrentEditedBone.Anchor) { return((NPVoxISceneEditable t) => { NPVoxBone.GetBoneByID(ref ((NPVoxSkeletonBuilder)t).AllBones, CurrentEditedBone.ID).Anchor = offset; return true; }); } } return(null); }
override protected NPVoxModel CreateProduct(NPVoxModel reuse = null) { if (Input == null) { return(NPVoxModel.NewInvalidInstance(reuse, "No Input Setup")); } NPVoxModel model = ((NPVoxIModelFactory)Input).GetProduct(); if (model is NPVoxBoneModel) { Debug.LogError("cannot create bone model on top of another bone model"); return(model); } NPVoxBoneModel newModel = NPVoxBoneModel.NewInstance(model.Size, reuse as NPVoxBoneModel); newModel.CopyOver(model); // setup bone masks newModel.AllBones = NPVoxBone.CloneBones(AllBones); for (int i = 0; i < AllBones.Length; i++) { NPVoxBone bone = AllBones[i]; List <NPVoxBox> boxes = AllBoxes[i].Boxes; if (boxes != null) { foreach (NPVoxBox box in boxes) { foreach (NPVoxCoord coord in box.Enumerate()) { newModel.AddBoneMask(coord, 1u << (bone.ID - 1)); } } } } return(newModel); }
public static uint GetMaskWithDescendants(ref NPVoxBone[] allBones, uint mask) { uint completeMask = mask; for (int i = 0; i < 32; i++) { int id = i + 1; if (((mask >> i) & 0x1) != 0) { NPVoxBone bone = GetBoneByID(ref allBones, id); if (bone != null) { NPVoxBone[] descendants = bone.GetDescendants(allBones); foreach (NPVoxBone descendant in descendants) { completeMask |= (1u << (descendant.ID - 1)); } } } } return(completeMask); }
public NPVoxBone[] GetChildren(NPVoxBone[] allBones) { int numBones = 0; foreach (NPVoxBone bone in allBones) { if (bone != null && bone.ID > 0 && bone.ParentID == this.ID) { numBones++; } } NPVoxBone[] bones = new NPVoxBone[numBones]; numBones = 0; foreach (NPVoxBone bone in allBones) { if (bone != null && bone.ID > 0 && bone.ParentID == this.ID) { bones[numBones++] = bone; } } return(bones); }
public static void DeleteBone(ref NPVoxBone[] allBones, NPVoxBone bone) { allBones[bone.ID - 1].ID = -1; }
override protected NPVoxModel CreateProduct(NPVoxModel reuse = null) { if (Input == null) { return(NPVoxModel.NewInvalidInstance(reuse, "Input was null")); } NPVoxModel inputModel = ((NPVoxIModelFactory)Input).GetProduct(); bool hasVoxelGroups = inputModel.HasVoxelGroups(); if (AffectedArea.Equals(NPVoxBox.INVALID)) { NPVoxModel model = NPVoxModel.NewInstance(inputModel, reuse); model.CopyOver(inputModel); return(model); } NPVoxBox clampedBox = inputModel.Clamp(AffectedArea); NPVoxModel transformedModel = null; transformedModel = NPVoxModel.NewInstance(inputModel, reuse); if (hasVoxelGroups) { transformedModel.InitVoxelGroups(); } transformedModel.NumVoxelGroups = inputModel.NumVoxelGroups; transformedModel.NumVoxels = inputModel.NumVoxels; transformedModel.Colortable = inputModel.Colortable != null ? (Color32[])inputModel.Colortable.Clone() : null; transformedModel.Sockets = inputModel.Sockets != null ? (NPVoxSocket[])inputModel.Sockets.Clone() : null; NPVoxBoneModel transformedBoneModel = transformedModel as NPVoxBoneModel; NPVoxBoneModel inputBoneModel = inputModel as NPVoxBoneModel; bool isBoneModel = false; if (transformedBoneModel != null) { transformedBoneModel.AllBones = NPVoxBone.CloneBones(inputBoneModel.AllBones); isBoneModel = true; } byte brightenedColor = NPVoxModelUtils.FindUnusedColor(inputModel); if (brightenedColor == 0) { Debug.LogWarning("could not find a free color to brighten the model"); } Color32 brightenColor32 = inputModel.Colortable[brightenedColor]; foreach (NPVoxCoord coord in inputModel.EnumerateVoxels()) { if (!isBoneModel) { if (clampedBox.Contains(coord) && brightenedColor != 0) { brightenColor32 = inputModel.Colortable[inputModel.GetVoxel(coord)]; transformedModel.SetVoxel(coord, brightenedColor); } else { transformedModel.SetVoxel(coord, inputModel.GetVoxel(coord)); } } else { if (hiddenBonesMask == 0 || !inputBoneModel.IsInBoneMask(coord, hiddenBonesMask)) { if (clampedBox.Contains(coord) && brightenedColor != 0 && inputBoneModel.IsInBoneMask(coord, boneMask)) { brightenColor32 = inputModel.Colortable[inputModel.GetVoxel(coord)]; transformedModel.SetVoxel(coord, brightenedColor); } else { transformedModel.SetVoxel(coord, inputModel.GetVoxel(coord)); } } transformedBoneModel.SetBoneMask(coord, inputBoneModel.GetBoneMask(coord)); } if (hasVoxelGroups) { transformedModel.SetVoxelGroup(coord, inputModel.GetVoxelGroup(coord)); } } if (brightenedColor != 0) { transformedModel.Colortable[brightenedColor] = NPVoxModelUtils.BrightenColor(brightenColor32); } transformedModel.RecalculateNumVoxels(true); return(transformedModel); }
public void DeleteBone(NPVoxBone bone) { Undo.RecordObject(this, "Delete Bone"); NPVoxBone.DeleteBone(ref AllBones, bone); }
public static NPVoxModel Transform(NPVoxModel sourceModel, NPVoxBox affectedArea, Matrix4x4 transformMatrix, ResolveConflictMethodType resolveConflictMethod = ResolveConflictMethodType.CLOSEST, NPVoxModel reuse = null) { NPVoxBox clampedBox = sourceModel.Clamp(affectedArea); // calculate size & offset for new model NPVoxCoord size = sourceModel.Size; NPVoxCoord offset = NPVoxCoord.ZERO; { NPVoxBox parentBounds = sourceModel.BoundingBox; NPVoxBox thisBounds = parentBounds.Clone(); // transform voxels foreach (NPVoxCoord coord in clampedBox.Enumerate()) { Vector3 saveCoord = transformMatrix.MultiplyPoint(NPVoxCoordUtil.ToVector(coord)); NPVoxCoord newCoord = NPVoxCoordUtil.ToCoord(saveCoord); if (!sourceModel.IsInside(newCoord)) { thisBounds.EnlargeToInclude(newCoord); } } // transform sockets foreach (NPVoxSocket socket in sourceModel.Sockets) { NPVoxCoord newCoord = NPVoxCoordUtil.ToCoord(transformMatrix.MultiplyPoint(NPVoxCoordUtil.ToVector(socket.Anchor))); if (clampedBox.Contains(socket.Anchor) && !sourceModel.IsInside(newCoord)) { thisBounds.EnlargeToInclude(newCoord); } } CalculateResizeOffset(parentBounds, thisBounds, out offset, out size); } bool hasVoxelGroups = sourceModel.HasVoxelGroups(); NPVoxBoneModel sourceBoneModel = sourceModel as NPVoxBoneModel; bool hasBoneGropus = sourceBoneModel != null; NPVoxModel transformedModel = NPVoxModel.NewInstance(sourceModel, size, reuse); NPVoxBoneModel transformedBoneModel = transformedModel as NPVoxBoneModel; if (hasVoxelGroups) { transformedModel.InitVoxelGroups(); transformedModel.NumVoxelGroups = sourceModel.NumVoxelGroups; } if (hasBoneGropus) { transformedBoneModel.AllBones = NPVoxBone.CloneBones(sourceBoneModel.AllBones); } // 1. copy all voxels over that are not affected by the transformation transformedModel.NumVoxels = sourceModel.NumVoxels; transformedModel.Colortable = sourceModel.Colortable; foreach (NPVoxCoord coord in sourceModel.EnumerateVoxels()) { NPVoxCoord movedCoord = coord + offset; if (!clampedBox.Contains(coord)) { transformedModel.SetVoxel(movedCoord, sourceModel.GetVoxel(coord)); if (hasVoxelGroups) { transformedModel.SetVoxelGroup(movedCoord, sourceModel.GetVoxelGroup(coord)); } if (hasBoneGropus) { transformedBoneModel.SetBoneMask(movedCoord, sourceBoneModel.GetBoneMask(coord)); } } } // 2. copy all voxels that can be tranformed without conflict, Dictionary <NPVoxCoord, Vector3> conflictVoxels = new Dictionary <NPVoxCoord, Vector3>(); foreach (NPVoxCoord sourceCoord in clampedBox.Enumerate()) { if (sourceModel.HasVoxelFast(sourceCoord)) { Vector3 saveCoord = transformMatrix.MultiplyPoint(NPVoxCoordUtil.ToVector(sourceCoord)); Vector3 targetCoordSave = saveCoord + NPVoxCoordUtil.ToVector(offset); NPVoxCoord targetCoord = NPVoxCoordUtil.ToCoord(targetCoordSave); if (!transformedModel.HasVoxelFast(targetCoord)) { transformedModel.SetVoxel(targetCoord, sourceModel.GetVoxel(sourceCoord)); if (hasVoxelGroups) { transformedModel.SetVoxelGroup(targetCoord, sourceModel.GetVoxelGroup(sourceCoord)); } if (hasBoneGropus) { transformedBoneModel.SetBoneMask(targetCoord, sourceBoneModel.GetBoneMask(sourceCoord)); } } else { conflictVoxels[sourceCoord] = targetCoordSave; } } } // 3. try to fit in voxels that had conflicts int numberOfConflictsSolved = 0; if (resolveConflictMethod != ResolveConflictMethodType.NONE) { foreach (NPVoxCoord sourceCoord in conflictVoxels.Keys) { if (sourceModel.HasVoxelFast(sourceCoord)) { Vector3 targetSaveCoord = conflictVoxels[sourceCoord]; NPVoxCoord nearbyCoord = GetNearbyCoord(transformedModel, targetSaveCoord, resolveConflictMethod); if (!nearbyCoord.Equals(NPVoxCoord.INVALID)) { transformedModel.SetVoxel(nearbyCoord, sourceModel.GetVoxel(sourceCoord)); if (hasVoxelGroups) { transformedModel.SetVoxelGroup(nearbyCoord, sourceModel.GetVoxelGroup(sourceCoord)); } if (hasBoneGropus) { transformedBoneModel.SetBoneMask(nearbyCoord, sourceBoneModel.GetBoneMask(sourceCoord)); } numberOfConflictsSolved++; } } } if (numberOfConflictsSolved != conflictVoxels.Count) { Debug.Log(string.Format("transformation has resolved {0}/{1} conflicting voxels", numberOfConflictsSolved, conflictVoxels.Count)); } } // 4. transform all sockets NPVoxSocket[] sockets = new NPVoxSocket[sourceModel.Sockets.Length]; for (int i = 0; i < sockets.Length; i++) { NPVoxSocket socket = sourceModel.Sockets[i]; if (clampedBox.Contains(socket.Anchor)) { // transform anchor Vector3 saveOriginalAnchor = NPVoxCoordUtil.ToVector(socket.Anchor); Vector3 saveTargetAnchor = transformMatrix.MultiplyPoint(saveOriginalAnchor) + NPVoxCoordUtil.ToVector(offset); socket.Anchor = NPVoxCoordUtil.ToCoord(saveTargetAnchor); // transform Quaternion Quaternion originalRotation = Quaternion.Euler(socket.EulerAngles); Matrix4x4 rotated = (Matrix4x4.TRS(Vector3.zero, originalRotation, Vector3.one) * transformMatrix); socket.EulerAngles = Matrix4x4Util.GetRotation(rotated).eulerAngles; } else { socket.Anchor = socket.Anchor + offset; } sockets[i] = socket; } transformedModel.Sockets = sockets; // 5. count all voxels transformedModel.NumVoxels = transformedModel.NumVoxels - (conflictVoxels.Count - numberOfConflictsSolved); transformedModel.RecalculateNumVoxels(true); return(transformedModel); }
private bool DrawBone(int currentLevel, NPVoxBone bone, bool isRoot, int numSiblings, float lastY) { EditorGUILayout.BeginHorizontal(); NPVoxBone[] bones = bone.GetChildren(AllBones); if (CurrentEditedBone == bone) { if (GUILayout.Button("Close", GUILayout.Width(40))) { CurrentEditedBone = null; CurrentEditedBox = null; return(true); } } else { if (GUILayout.Button("Edit", GUILayout.Width(40))) { CurrentEditedBone = bone; CurrentEditedBox = GetBoxes(bone).Count > 0 ? GetBoxes(bone)[0] : null; return(true); } } GUILayout.Space(10f * currentLevel); Rect rect = GUILayoutUtility.GetLastRect(); if (numSiblings > 1) { float currentX = rect.xMin + 10f * currentLevel; Handles.color = Color.black; Handles.DrawLine(new Vector2(currentX, lastY + 18), new Vector2(currentX, rect.yMax + 10)); Handles.DrawLine(new Vector2(currentX, rect.yMax + 10), new Vector2(currentX + 10, rect.yMax + 10)); } if (bones.Length > 1) { lastY = rect.y; } EditorGUILayout.BeginVertical(); string newName = EditorGUILayout.TextField(bone.Name); if (newName != bone.Name) { bone.Name = newName; return(true); } if (CurrentEditedBone == bone) { EditorGUILayout.BeginHorizontal(); GUILayout.Space(10f); if (bone.ID != 0 && bones.Length == 0 && GUILayout.Button("Delete ")) { DeleteBone(bone); CurrentEditedBox = null; CurrentEditedBone = null; return(true); } if (GUILayout.Button("+ Bone")) { CurrentEditedBox = null; CurrentEditedBone = AddBone(bone); return(true); } if (!isRoot) { if (GUILayout.Button("+ Box ")) { CurrentEditedBox = AddBox(bone); return(true); } if (CurrentCopiedBox != null && GUILayout.Button("+ Paste")) { CurrentEditedBox = AddBox(bone); CurrentEditedBox.LeftDownBack = CurrentCopiedBox.LeftDownBack; CurrentEditedBox.RightUpForward = CurrentCopiedBox.RightUpForward; return(true); } List <NPVoxBox> boxes = GetBoxes(bone); int i = 0; foreach (NPVoxBox box in boxes) { EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(10f); EditorGUILayout.LabelField("(Box: " + i + ")", GUILayout.Width(100)); if (box != CurrentEditedBox) { if (GUILayout.Button("Edit")) { CurrentEditedBox = box; return(true); } } else { if (GUILayout.Button("Close")) { CurrentEditedBox = null; return(true); } } if (GUILayout.Button("Delete")) { DeleteBox(bone, box); CurrentEditedBox = null; return(true); } if (GUILayout.Button("Copy")) { CurrentCopiedBox = box; return(true); } i++; } } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.LabelField("(ID: " + bone.ID + ")", GUILayout.Width(100)); EditorGUILayout.EndHorizontal(); for (int i = 0; i < bones.Length; i++) { NPVoxBone child = bones[i]; if (child != null && DrawBone(currentLevel + 1, child, false, bones.Length, lastY)) { return(true); } } return(false); }