void OnDrawGizmos() { for (int i = 0; i < gizmosInfos.Count; i++) { Hashtable info = gizmosInfos[i]; GizmoAction action = (GizmoAction)info["action"]; switch (action) { case GizmoAction.COLOR: Gizmos.color = (Color)info["color"]; #if UNITY_EDITOR UnityEditor.Handles.color = (Color)info["color"]; #endif break; case GizmoAction.PLANE: DrawPlane((Vector3)info["position"], (Vector3)info["normal"], (float)info["size"]); break; case GizmoAction.LINE: Gizmos.DrawLine((Vector3)info["p1"], (Vector3)info["p2"]); break; case GizmoAction.ARROW: DrawArrow((Vector3)info["position"], (Vector3)info["dir"]); break; case GizmoAction.CONE: DrawCone((Vector3)info["position"], (Vector3)info["dir"], (Vector3)info["normal"], (float)info["distance"], (float)info["angle"]); break; case GizmoAction.TEXT: DrawText((string)info["text"], (Vector3)info["position"]); break; case GizmoAction.SPHERE: Gizmos.DrawSphere((Vector3)info["position"], (float)info["radius"]); break; case GizmoAction.WIRESPHERE: Gizmos.DrawWireSphere((Vector3)info["position"], (float)info["radius"]); break; case GizmoAction.WIRECUBE: Gizmos.DrawWireCube((Vector3)info["position"], Vector3.one * (float)info["size"]); break; } } }
private void UpdateGizmoHighlighting(GizmoAction gizmoAction) { if (currentActiveGizmoEntity == null) { return; } var gizmoTranslationHierarchicalParent = currentActiveGizmoEntity.Transformation; foreach (var child in gizmoTranslationHierarchicalParent.Children) { var childGizmoAction = child.Entity.Get(GizmoActionKey); bool isActiveGizmo = ((childGizmoAction & gizmoAction) == childGizmoAction); child.Entity.Get(ModelComponent.Key).MeshParameters.Set(MaterialKeys.DiffuseColor, isActiveGizmo ? Color.Yellow : child.Entity.Get(GizmoColorKey)); } }
// Add new GizmoDraw public void AddGizmoAction(GizmoAction gizmo) { GizmoActions.Add(gizmo); }
private void RotateEntity(EngineContext engineContext, Entity entity, GizmoAction currentGizmoAction, Vector2 delta) { // Get current transformation component var transformationComponent = entity != null ? entity.Transformation : null; //transformationComponent.Rotation = pickingObjectRotation; if (delta == Vector2.Zero || transformationComponent == null) { return; } var transformationComponentValues = transformationComponent.Value as TransformationTRS; if (transformationComponentValues == null) { return; } Matrix currentRotationMatrix; Vector3 pickingGizmoRotationLocal; transformationComponentValues.LocalMatrix.DecomposeXYZ(out pickingGizmoRotationLocal); var currentRotationMatrixLocal = Matrix.RotationX(pickingGizmoRotationLocal.X) * Matrix.RotationY(pickingGizmoRotationLocal.Y) * Matrix.RotationZ(pickingGizmoRotationLocal.Z); var parentMatrix = transformationComponent.Parent != null ? transformationComponent.Parent.WorldMatrix : Matrix.Identity; var parentMatrixInverse = Matrix.Invert(parentMatrix); float deltaRotation = (delta.X + delta.Y) * 0.01f; Vector3 rotationBefore; currentRotationMatrixLocal.DecomposeXYZ(out rotationBefore); // Apply the rotation in parent local space if (currentGizmoAction == GizmoAction.RotationX) { currentRotationMatrix = currentRotationMatrixLocal * parentMatrixInverse * Matrix.RotationX(deltaRotation) * parentMatrix; } else if (currentGizmoAction == GizmoAction.RotationY) { currentRotationMatrix = currentRotationMatrixLocal * parentMatrixInverse * Matrix.RotationY(deltaRotation) * parentMatrix; } else if (currentGizmoAction == GizmoAction.RotationZ) { currentRotationMatrix = currentRotationMatrixLocal * parentMatrixInverse * Matrix.RotationZ(deltaRotation) * parentMatrix; } else { throw new NotImplementedException(); } Vector3 rotationAfter; currentRotationMatrix.DecomposeXYZ(out rotationAfter); transformationComponentValues.RotationEuler += rotationAfter - rotationBefore; }
private void MoveEntity(EngineContext engineContext, Entity entity, GizmoAction currentGizmoAction, Vector3 pickingGizmoOrigin, Vector3 pickingObjectOrigin, Vector2 delta) { var renderingSetup = RenderingSetup.Singleton; // Get current transformation component var transformationComponent = entity != null ? entity.Transformation : null; if (delta == Vector2.Zero || transformationComponent == null) { return; } var transformationComponentValues = transformationComponent.Value as TransformationTRS; if (transformationComponentValues == null) { return; } var viewParameters = renderingSetup.MainPlugin.ViewParameters; transformationComponentValues.Translation = pickingObjectOrigin; if ((currentGizmoAction & GizmoAction.Translation) != GizmoAction.None) { var axes = new Vector3[3]; int axisCount = 0; if ((currentGizmoAction & GizmoAction.TranslationX) != GizmoAction.None) { axes[axisCount++] = Vector3.UnitX; } if ((currentGizmoAction & GizmoAction.TranslationY) != GizmoAction.None) { axes[axisCount++] = Vector3.UnitY; } if ((currentGizmoAction & GizmoAction.TranslationZ) != GizmoAction.None) { axes[axisCount++] = Vector3.UnitZ; } if (axisCount == 3) { throw new NotImplementedException("Translation should only act on two axes."); } var viewProj = viewParameters.Get(TransformationKeys.View) * viewParameters.Get(TransformationKeys.Projection); // Only one axis, we should find the best second "helper" axis to build our plan. // Currently, it looks for another unit axis to build that plan (the one that is the most "perpendicular" to current axis in screenspace). if (axisCount == 1) { Vector3 projectedAxis; Vector3.TransformNormal(ref axes[0], ref viewProj, out projectedAxis); var unitX = Vector3.TransformNormal(Vector3.UnitX, viewProj); var unitY = Vector3.TransformNormal(Vector3.UnitY, viewProj); var unitZ = Vector3.TransformNormal(Vector3.UnitZ, viewProj); // Ignore Z axis (depth) projectedAxis.Z = 0.0f; unitX.Z = 0.0f; unitY.Z = 0.0f; unitZ.Z = 0.0f; // Normalize projectedAxis.Normalize(); unitX.Normalize(); unitY.Normalize(); unitZ.Normalize(); var dotX = Math.Abs(Vector3.Dot(unitX, projectedAxis)); var dotY = Math.Abs(Vector3.Dot(unitY, projectedAxis)); var dotZ = Math.Abs(Vector3.Dot(unitZ, projectedAxis)); if (dotX < dotY && dotX < dotZ) { axes[1] = Vector3.UnitX; } else if (dotY < dotZ) { axes[1] = Vector3.UnitY; } else { axes[1] = Vector3.UnitZ; } } var parentMatrix = transformationComponent.Parent != null ? transformationComponent.Parent.WorldMatrix : Matrix.Identity; parentMatrix.Invert(); transformationComponentValues.Translation += Vector3.TransformNormal(ComputePickingDelta(engineContext, axes[0], axes[1], ref viewProj, pickingGizmoOrigin, pickingObjectOrigin, delta), parentMatrix); if (axisCount == 2) { transformationComponentValues.Translation += Vector3.TransformNormal(ComputePickingDelta(engineContext, axes[1], axes[0], ref viewProj, pickingGizmoOrigin, pickingObjectOrigin, delta), parentMatrix); } } }
private void RefreshGizmos(GizmoAction currentGizmoAction) { var renderingSetup = RenderingSetup.Singleton; // Delay gizmo change until current action is finished if (currentActiveGizmoActionMode != ActiveGizmoActionMode && currentGizmoAction == GizmoAction.None) { if (currentActiveGizmoEntity != null) { editorEntitySystem.Entities.Remove(currentActiveGizmoEntity); } if (ActiveGizmoActionMode == GizmoAction.Translation) { currentActiveGizmoEntity = translationGizmo; } else if (ActiveGizmoActionMode == GizmoAction.Rotation) { currentActiveGizmoEntity = rotationGizmo; } else { currentActiveGizmoEntity = null; } currentActiveGizmoActionMode = ActiveGizmoActionMode; } if (currentActiveGizmoEntity == null) { return; } TransformationComponent[] selectedTransformations; if (selectedEntities != null && (selectedTransformations = selectedEntities.Select(x => x.Entity.Transformation).Where(x => x != null && x.Value is TransformationTRS).ToArray()).Length > 0) { if (!editorEntitySystem.Entities.Contains(currentActiveGizmoEntity)) { editorEntitySystem.Add(currentActiveGizmoEntity); } // TODO: Only act on "current" gizmo? var gizmoTransformation = (TransformationTRS)currentActiveGizmoEntity.Transformation.Value; var translationSum = Vector3.Zero; // Make average of selected objects origin to position gizmo foreach (var selectedTransformation in selectedTransformations) { // Compensate scaling // TODO: Negative/zero scaling? var parentMatrix = selectedTransformation.WorldMatrix; translationSum += parentMatrix.TranslationVector; } gizmoTransformation.Translation = translationSum / selectedTransformations.Length; // Make gizmo size constant (screen-space) -- only if not currently being used // TODO: Currently FOV-dependent if (currentGizmoAction == GizmoAction.None) { var view = renderingSetup.MainPlugin.ViewParameters.Get(TransformationKeys.View); var worldView = view; var position = Vector3.TransformCoordinate(gizmoTransformation.Translation, worldView); gizmoTransformation.Scaling = new Vector3(position.Z * 0.01f); } } else { if (editorEntitySystem.Entities.Contains(currentActiveGizmoEntity)) { editorEntitySystem.Entities.Remove(currentActiveGizmoEntity); } } }
private void UpdateGizmoHighlighting(GizmoAction gizmoAction) { if (currentActiveGizmoEntity == null) return; var gizmoTranslationHierarchicalParent = currentActiveGizmoEntity.Transformation; foreach (var child in gizmoTranslationHierarchicalParent.Children) { var childGizmoAction = child.Entity.Get(GizmoActionKey); bool isActiveGizmo = ((childGizmoAction & gizmoAction) == childGizmoAction); child.Entity.Get(ModelComponent.Key).MeshParameters.Set(MaterialKeys.DiffuseColor, isActiveGizmo ? Color.Yellow : child.Entity.Get(GizmoColorKey)); } }
private void RotateEntity(EngineContext engineContext, Entity entity, GizmoAction currentGizmoAction, Vector2 delta) { // Get current transformation component var transformationComponent = entity != null ? entity.Transformation : null; //transformationComponent.Rotation = pickingObjectRotation; if (delta == Vector2.Zero || transformationComponent == null) return; var transformationComponentValues = transformationComponent.Value as TransformationTRS; if (transformationComponentValues == null) return; Matrix currentRotationMatrix; Vector3 pickingGizmoRotationLocal; transformationComponentValues.LocalMatrix.DecomposeXYZ(out pickingGizmoRotationLocal); var currentRotationMatrixLocal = Matrix.RotationX(pickingGizmoRotationLocal.X) * Matrix.RotationY(pickingGizmoRotationLocal.Y) * Matrix.RotationZ(pickingGizmoRotationLocal.Z); var parentMatrix = transformationComponent.Parent != null ? transformationComponent.Parent.WorldMatrix : Matrix.Identity; var parentMatrixInverse = Matrix.Invert(parentMatrix); float deltaRotation = (delta.X + delta.Y) * 0.01f; Vector3 rotationBefore; currentRotationMatrixLocal.DecomposeXYZ(out rotationBefore); // Apply the rotation in parent local space if (currentGizmoAction == GizmoAction.RotationX) { currentRotationMatrix = currentRotationMatrixLocal * parentMatrixInverse * Matrix.RotationX(deltaRotation) * parentMatrix; } else if (currentGizmoAction == GizmoAction.RotationY) { currentRotationMatrix = currentRotationMatrixLocal * parentMatrixInverse * Matrix.RotationY(deltaRotation) * parentMatrix; } else if (currentGizmoAction == GizmoAction.RotationZ) { currentRotationMatrix = currentRotationMatrixLocal * parentMatrixInverse * Matrix.RotationZ(deltaRotation) * parentMatrix; } else { throw new NotImplementedException(); } Vector3 rotationAfter; currentRotationMatrix.DecomposeXYZ(out rotationAfter); transformationComponentValues.RotationEuler += rotationAfter - rotationBefore; }
private void MoveEntity(EngineContext engineContext, Entity entity, GizmoAction currentGizmoAction, Vector3 pickingGizmoOrigin, Vector3 pickingObjectOrigin, Vector2 delta) { var renderingSetup = RenderingSetup.Singleton; // Get current transformation component var transformationComponent = entity != null ? entity.Transformation : null; if (delta == Vector2.Zero || transformationComponent == null) return; var transformationComponentValues = transformationComponent.Value as TransformationTRS; if (transformationComponentValues == null) return; var viewParameters = renderingSetup.MainPlugin.ViewParameters; transformationComponentValues.Translation = pickingObjectOrigin; if ((currentGizmoAction & GizmoAction.Translation) != GizmoAction.None) { var axes = new Vector3[3]; int axisCount = 0; if ((currentGizmoAction & GizmoAction.TranslationX) != GizmoAction.None) axes[axisCount++] = Vector3.UnitX; if ((currentGizmoAction & GizmoAction.TranslationY) != GizmoAction.None) axes[axisCount++] = Vector3.UnitY; if ((currentGizmoAction & GizmoAction.TranslationZ) != GizmoAction.None) axes[axisCount++] = Vector3.UnitZ; if (axisCount == 3) throw new NotImplementedException("Translation should only act on two axes."); var viewProj = viewParameters.Get(TransformationKeys.View) * viewParameters.Get(TransformationKeys.Projection); // Only one axis, we should find the best second "helper" axis to build our plan. // Currently, it looks for another unit axis to build that plan (the one that is the most "perpendicular" to current axis in screenspace). if (axisCount == 1) { Vector3 projectedAxis; Vector3.TransformNormal(ref axes[0], ref viewProj, out projectedAxis); var unitX = Vector3.TransformNormal(Vector3.UnitX, viewProj); var unitY = Vector3.TransformNormal(Vector3.UnitY, viewProj); var unitZ = Vector3.TransformNormal(Vector3.UnitZ, viewProj); // Ignore Z axis (depth) projectedAxis.Z = 0.0f; unitX.Z = 0.0f; unitY.Z = 0.0f; unitZ.Z = 0.0f; // Normalize projectedAxis.Normalize(); unitX.Normalize(); unitY.Normalize(); unitZ.Normalize(); var dotX = Math.Abs(Vector3.Dot(unitX, projectedAxis)); var dotY = Math.Abs(Vector3.Dot(unitY, projectedAxis)); var dotZ = Math.Abs(Vector3.Dot(unitZ, projectedAxis)); if (dotX < dotY && dotX < dotZ) axes[1] = Vector3.UnitX; else if (dotY < dotZ) axes[1] = Vector3.UnitY; else axes[1] = Vector3.UnitZ; } var parentMatrix = transformationComponent.Parent != null ? transformationComponent.Parent.WorldMatrix : Matrix.Identity; parentMatrix.Invert(); transformationComponentValues.Translation += Vector3.TransformNormal(ComputePickingDelta(engineContext, axes[0], axes[1], ref viewProj, pickingGizmoOrigin, pickingObjectOrigin, delta), parentMatrix); if (axisCount == 2) transformationComponentValues.Translation += Vector3.TransformNormal(ComputePickingDelta(engineContext, axes[1], axes[0], ref viewProj, pickingGizmoOrigin, pickingObjectOrigin, delta), parentMatrix); } }
private void RefreshGizmos(GizmoAction currentGizmoAction) { var renderingSetup = RenderingSetup.Singleton; // Delay gizmo change until current action is finished if (currentActiveGizmoActionMode != ActiveGizmoActionMode && currentGizmoAction == GizmoAction.None) { if (currentActiveGizmoEntity != null) editorEntitySystem.Entities.Remove(currentActiveGizmoEntity); if (ActiveGizmoActionMode == GizmoAction.Translation) { currentActiveGizmoEntity = translationGizmo; } else if (ActiveGizmoActionMode == GizmoAction.Rotation) { currentActiveGizmoEntity = rotationGizmo; } else { currentActiveGizmoEntity = null; } currentActiveGizmoActionMode = ActiveGizmoActionMode; } if (currentActiveGizmoEntity == null) return; TransformationComponent[] selectedTransformations; if (selectedEntities != null && (selectedTransformations = selectedEntities.Select(x => x.Entity.Transformation).Where(x => x != null && x.Value is TransformationTRS).ToArray()).Length > 0) { if (!editorEntitySystem.Entities.Contains(currentActiveGizmoEntity)) editorEntitySystem.Add(currentActiveGizmoEntity); // TODO: Only act on "current" gizmo? var gizmoTransformation = (TransformationTRS)currentActiveGizmoEntity.Transformation.Value; var translationSum = Vector3.Zero; // Make average of selected objects origin to position gizmo foreach (var selectedTransformation in selectedTransformations) { // Compensate scaling // TODO: Negative/zero scaling? var parentMatrix = selectedTransformation.WorldMatrix; translationSum += parentMatrix.TranslationVector; } gizmoTransformation.Translation = translationSum / selectedTransformations.Length; // Make gizmo size constant (screen-space) -- only if not currently being used // TODO: Currently FOV-dependent if (currentGizmoAction == GizmoAction.None) { var view = renderingSetup.MainPlugin.ViewParameters.Get(TransformationKeys.View); var worldView = view; var position = Vector3.TransformCoordinate(gizmoTransformation.Translation, worldView); gizmoTransformation.Scaling = new Vector3(position.Z * 0.01f); } } else { if (editorEntitySystem.Entities.Contains(currentActiveGizmoEntity)) editorEntitySystem.Entities.Remove(currentActiveGizmoEntity); } }
void OnDrawGizmos() { for (int i = 0; i < gizmosInfos.Count; i++) { Hashtable info = gizmosInfos[i]; GizmoAction action = (GizmoAction)info["action"]; // whatever the action, if it has a color embeded, it // should override Gizmos color for this call bool color_swapped = false; Color prev_color = Gizmos.color; if (info.ContainsKey("color") && action != GizmoAction.COLOR && info["color"] != null) { color_swapped = true; Color new_color = (Color)info["color"]; Gizmos.color = new_color; #if UNITY_EDITOR UnityEditor.Handles.color = new_color; #endif } switch (action) { case GizmoAction.COLOR: Gizmos.color = (Color)info["color"]; #if UNITY_EDITOR UnityEditor.Handles.color = (Color)info["color"]; #endif break; case GizmoAction.PLANE: DrawPlane((Vector3)info["position"], (Vector3)info["normal"], (float)info["size"]); break; case GizmoAction.LINE: Gizmos.DrawLine((Vector3)info["p1"], (Vector3)info["p2"]); break; case GizmoAction.ARROW: DrawArrow((Vector3)info["position"], (Vector3)info["dir"]); break; case GizmoAction.CONE: DrawCone((Vector3)info["position"], (Vector3)info["dir"], (Vector3)info["normal"], (float)info["distance"], (float)info["angle"]); break; case GizmoAction.TEXT: DrawText((string)info["text"], (Vector3)info["position"]); break; case GizmoAction.SPHERE: Gizmos.DrawSphere((Vector3)info["position"], (float)info["radius"]); break; case GizmoAction.WIRESPHERE: Gizmos.DrawWireSphere((Vector3)info["position"], (float)info["radius"]); break; case GizmoAction.WIRECUBE: Gizmos.DrawWireCube((Vector3)info["position"], Vector3.one * (float)info["size"]); break; } if (color_swapped) { Gizmos.color = prev_color; #if UNITY_EDITOR UnityEditor.Handles.color = prev_color; #endif } } }