public static NPVoxModel SocketTransform(NPVoxModel sourceModel, NPVoxModel targetModel, NPVoxSocket sourceSocket, NPVoxSocket targetSocket, ResolveConflictMethodType resolveConflictMethod = ResolveConflictMethodType.CLOSEST, NPVoxModel reuse = null)
    {
        NPVoxToUnity sourceVox2Unity = new NPVoxToUnity(sourceModel, Vector3.one);
        NPVoxToUnity targetVox2Unity = new NPVoxToUnity(targetModel, Vector3.one);

        Vector3    sourceAnchorPos = sourceVox2Unity.ToUnityPosition(sourceSocket.Anchor);
        Quaternion sourceRotation  = Quaternion.Euler(sourceSocket.EulerAngles);
        Vector3    targetAnchorPos = targetVox2Unity.ToUnityPosition(targetSocket.Anchor);
        Quaternion targetRotation  = Quaternion.Euler(targetSocket.EulerAngles);
        Vector3    diff            = sourceVox2Unity.ToSaveVoxDirection(targetAnchorPos - sourceAnchorPos);

        Matrix4x4 A = Matrix4x4.TRS(sourceVox2Unity.ToSaveVoxCoord(sourceAnchorPos), Quaternion.identity, Vector3.one);
        Matrix4x4 B = Matrix4x4.TRS(Vector3.zero, sourceRotation, Vector3.one).inverse *Matrix4x4.TRS(Vector3.zero, targetRotation, Vector3.one);
        Matrix4x4 C = Matrix4x4.TRS(-sourceVox2Unity.ToSaveVoxCoord(sourceAnchorPos), Quaternion.identity, Vector3.one);
        Matrix4x4 D = Matrix4x4.TRS(diff, Quaternion.identity, Vector3.one);

        Matrix4x4 transformMatrix = D * A * B * C;

        return(Transform(sourceModel, sourceModel.BoundingBox, transformMatrix, resolveConflictMethod, reuse));
    }
    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);
    }
    public System.Func <NPVoxISceneEditable, bool> DrawSceneTool(NPVoxToUnity npVoxToUnity, Transform transform, int tool)
    {
        if (Input == null)
        {
            return(null);
        }

        NPVoxModel model = ((NPVoxIModelFactory)Input).GetProduct() as NPVoxModel;

        if (!model)
        {
            return(null);
        }

        if (!(PreviousFrame is NPVoxIModelFactory))
        {
            return(null);
        }

        if (SocketOffsets.Length < 4 || ControlPointOffsets.Length < 4)
        {
            ResetSceneTools();
        }

        NPVoxToUnity sourceN2U     = new NPVoxToUnity(((NPVoxIModelFactory)PreviousFrame).GetProduct(), npVoxToUnity.VoxeSize);
        NPVoxSocket  sourceSocket1 = ((NPVoxIModelFactory)PreviousFrame).GetProduct().GetSocketByName(SocketName1);
        NPVoxSocket  sourceSocket2 = ((NPVoxIModelFactory)PreviousFrame).GetProduct().GetSocketByName(SocketName2);

        NPVoxModel targetModel = model;

        if (TargetFrame is NPVoxIModelFactory)
        {
            targetModel = ((NPVoxIModelFactory)TargetFrame).GetProduct() as NPVoxModel;
        }
        NPVoxToUnity targetN2U = new NPVoxToUnity(targetModel, npVoxToUnity.VoxeSize);

        NPVoxSocket targetSocket1 = targetModel.GetSocketByName(SocketName1);
        NPVoxSocket targetSocket2 = targetModel.GetSocketByName(SocketName2);

        if (targetSocket1.IsInvalid())
        {
            Debug.LogWarning("SocketName1 not found in targetModel");
            return(null);
        }

        if (targetSocket2.IsInvalid())
        {
            Debug.LogWarning("SocketName2 not found in targetModel");
            return(null);
        }

        NPVoxSocket[] sockets = new NPVoxSocket[4];
        sockets[INDEX_SOURCE_1] = sourceSocket1;
        sockets[INDEX_SOURCE_2] = sourceSocket2;
        sockets[INDEX_TARGET_1] = targetSocket1;
        sockets[INDEX_TARGET_2] = targetSocket2;

        NPVoxToUnity[] n2u = new NPVoxToUnity[4];
        n2u[INDEX_SOURCE_1] = sourceN2U;
        n2u[INDEX_SOURCE_2] = sourceN2U;
        n2u[INDEX_TARGET_1] = targetN2U;
        n2u[INDEX_TARGET_2] = targetN2U;

        NPVoxToUnity n = n2u[currentEditedSocket];

        Vector3 pos = n.ToUnityPosition(sockets[currentEditedSocket].Anchor);

        if (tool == 0)
        {
            if (Event.current.type == EventType.MouseDown)
            {
                currentEditedSocket = (currentEditedSocket + 1) % 4;
            }

            switch (currentEditedSocket)
            {
            case INDEX_TARGET_1:
                Handles.color = Color.green;
                break;

            case INDEX_TARGET_2:
                Handles.color = Color.green;
                break;

            case INDEX_SOURCE_1:
                Handles.color = Color.yellow;
                break;

            case INDEX_SOURCE_2:
                Handles.color = Color.yellow;
                break;
            }
            Handles.CubeCap(0, pos, Quaternion.identity, 0.5f);
        }

        // offset
        Vector3 offset = n.ToUnityDirection(SocketOffsets[currentEditedSocket]);

        if (tool == 1)
        {
            offset = n.ToSaveVoxDirection(Handles.PositionHandle(pos + offset, Quaternion.identity) - pos);
            if (offset != SocketOffsets[currentEditedSocket])
            {
                return((NPVoxISceneEditable t) =>
                {
                    (t as NPVoxTrailGenerator).SocketOffsets[currentEditedSocket] = offset;
                    return true;
                });
            }
        }

        Vector3 controlOffset = n.ToUnityDirection(ControlPointOffsets[currentEditedSocket]);

        // Control Point
        if (tool == 2)
        {
            controlOffset = n.ToSaveVoxDirection(Handles.PositionHandle(pos + offset + controlOffset, Quaternion.identity) - pos - offset);
            if (controlOffset != ControlPointOffsets[currentEditedSocket])
            {
                return((NPVoxISceneEditable t) =>
                {
                    (t as NPVoxTrailGenerator).ControlPointOffsets[currentEditedSocket] = controlOffset;
                    return true;
                });
            }
        }

        return(null);
    }
    public System.Func <NPVoxISceneEditable, bool> DrawSceneTool(NPVoxToUnity npVoxToUnity, Transform transform, int tool)
    {
        if (Input == null)
        {
            return(null);
        }

        NPVoxModel model = ((NPVoxIModelFactory)Input).GetProduct() as NPVoxModel;

        if (!model)
        {
            return(null);
        }

        Vector3 pivot = npVoxToUnity.ToUnityPosition(GetPivot());

        // Position handle
        if (tool == 0)
        {
            Vector3 oldTranslation = GetTranslation();
            Vector3 newTranslation = npVoxToUnity.ToSaveVoxDirection(
                Handles.PositionHandle(npVoxToUnity.ToUnityDirection(oldTranslation) + pivot, Quaternion.identity) - pivot
                );
            if (!newTranslation.Equals(oldTranslation))
            {
                return((NPVoxISceneEditable t) =>
                {
                    (t as NPVoxModelTransformerBase).SetTranslation(newTranslation);
                    return true;
                });
            }
        }

        // Quaternion Handle
        if (tool == 1)
        {
            Quaternion oldQuaternion = GetRotation();
            Quaternion newQuaternion = Handles.RotationHandle(oldQuaternion, pivot);
            if (!newQuaternion.Equals(oldQuaternion))
            {
                return((NPVoxISceneEditable t) =>
                {
                    (t as NPVoxModelTransformerBase).SetRotation(newQuaternion);
                    return true;
                });
            }
        }

        // Scale Handle
        if (tool == 2)
        {
            Vector3 oldScale = GetScale();
            Vector3 newScale = Handles.ScaleHandle(oldScale, pivot, GetRotation(), 1.0f);
            if (!newScale.Equals(oldScale))
            {
                return((NPVoxISceneEditable t) =>
                {
                    (t as NPVoxModelTransformerBase).SetScale(newScale);
                    return true;
                });
            }
        }

        // Pivot Handle
        if (tool == 3)
        {
            Vector3 newPivot = Handles.PositionHandle(pivot, Quaternion.identity);
            if (!newPivot.Equals(pivot))
            {
                return((NPVoxISceneEditable t) =>
                {
                    (t as NPVoxModelTransformerBase).SetPivot(newPivot);
                    return true;
                });
            }
        }
        return(null);
    }