/// There is no reasonable way for a caller to know what to pass for "endCustomDimension", /// because moving or scaling the widget (with some change in endXf) may cause the widget's /// CustomDimension values to change, too. /// /// Typically, a caller will pass widget.CustomDimension and assume that this /// is the correct value. Or, callers will go through some custom API on the widget /// (see CubeStencil.RecordAndApplyScaleToAxis) which has knowledge of its own internals /// and can compute the proper endCustomDimension to pass. public MoveWidgetCommand(GrabWidget widget, TrTransform endXf, Vector3 endCustomDimension, bool final = false, BaseCommand parent = null) : base(parent) { m_Widget = widget; m_Final = final; m_StartTransform = widget.LocalTransform; if (widget is StencilWidget) { m_Type = Type.Guide; } else if (widget is MediaWidget) { m_Type = Type.Media; m_StartTransform.scale = widget.GetSignedWidgetSize(); } else if (widget is SymmetryWidget) { m_Type = Type.Symmetry; } else if (widget is SelectionWidget) { m_Type = Type.Selection; m_StartSelectionTransform = SelectionManager.m_Instance.SelectionTransform; m_EndSelectionTransform = SelectionManager.m_Instance.SelectionTransform; } m_CustomDimension.startState = widget.CustomDimension; m_EndTransform = endXf; m_CustomDimension.endState = endCustomDimension; }
// ------------------------------------------------------------------------------------------ // // Private Internals // ------------------------------------------------------------------------------------------ // override protected void OnReadResults() { // Mark results as ready. m_ResultCount = 0; if (m_ResultList != null) { m_ResultList.Clear(); } uint[] resultColors = GetTextureColors(); // // Process the color buffer into result objects, if requested. // UnityEngine.Profiling.Profiler.BeginSample("Intersection: Process Model Results"); HashSet <object> seen = AllocateHashSet(); uint c; for (int i = 0; i < resultColors.Length; i++) { if (m_ResultCount == m_MaxResults) { break; } c = resultColors[i]; if (c > 0) { // Don't bother looking up the batch if the exact result set wasn't requested. if (m_ResultList == null) { m_ResultCount++; continue; } ushort batchId = (ushort)((c & 0xffff0000) >> 16); GrabWidget widget = WidgetManager.m_Instance.GetBatch(batchId); if (widget == null) { continue; } if (!seen.Add(widget)) { continue; } m_ResultList.Add(new ModelResult { widget = widget }); m_ResultCount++; } } DeallocateHashSet(seen); UnityEngine.Profiling.Profiler.EndSample(); }
public void Init(Transform parent, GrabWidget parentWidget) { m_WorkingPenetrationScalar = m_PenetrationScalar; m_DestroyOnStateComplete = false; m_WobbleCountdown = 0.0f; m_Parent = parent; m_ParentWidgetScript = parentWidget; InitTransformedSpawnOffset(); }
protected override void OnRedo() { if (m_Widget != null) { // If we're re-doing this command and the widget exists, it's because we had previously // undone a creation. The widget will be hidden at this point, so we want to restore it, // much in the opposite way HideWidgetCommand works. // TODO: This function name is used more generally and should be renamed. m_Widget.gameObject.SetActive(true); m_Widget.RestoreFromToss(); } else { m_Widget = Object.Instantiate(m_Prefab); m_Widget.transform.position = m_SpawnXf.translation; // Widget type specific initialization. if (m_Widget is StencilWidget) { m_Widget.transform.parent = m_Canvas.transform; m_Widget.Show(true); } else if (m_Widget is ModelWidget) { // ModelWidget.Show(true) is not called here because the model must be assigned // before it can be turned on. } else if (m_Widget is ImageWidget) { m_Widget.transform.parent = m_Canvas.transform; m_Widget.Show(true); } else if (m_Widget is VideoWidget) { m_Widget.transform.parent = m_Canvas.transform; m_Widget.Show(true); } else if (m_Widget is CameraPathWidget) { m_Widget.transform.parent = m_Canvas.transform; m_Widget.transform.localPosition = Vector3.zero; m_Widget.transform.localRotation = Quaternion.identity; m_Widget.Show(true); App.Switchboard.TriggerCameraPathCreated(); WidgetManager.m_Instance.CameraPathsVisible = true; } m_Widget.InitIntroAnim(m_SpawnXf, m_EndXf, false, m_DesiredEndForward); m_TiltMeterCost = m_Widget.GetTiltMeterCost(); } WidgetManager.m_Instance.RefreshPinAndUnpinLists(); TiltMeterScript.m_Instance.AdjustMeterWithWidget(m_TiltMeterCost, up: true); m_TiltMeterCostUndone = false; }
private void AddToGroupToSelectedWidgets(SketchGroupTag group, GrabWidget widget) { if (!m_GroupToSelectedWidgets.TryGetValue(group, out var groupWidgets)) { groupWidgets = m_GroupToSelectedWidgets[group] = new HashSet <GrabWidget>(); } Debug.Assert(!groupWidgets.Contains(widget)); groupWidgets.Add(widget); App.Switchboard.TriggerSelectionChanged(); }
private void RemoveFromGroupToSelectedWidgets(SketchGroupTag group, GrabWidget widget) { var groupWidgets = m_GroupToSelectedWidgets[group]; groupWidgets.Remove(widget); if (groupWidgets.Count == 0) { m_GroupToSelectedWidgets.Remove(group); } App.Switchboard.TriggerSelectionChanged(); }
override protected bool HandleIntersectionWithWidget(GrabWidget widget) { if (widget.Pinned == m_InPinningMode) { return(false); } SketchMemoryScript.m_Instance.PerformAndRecordCommand( new PinWidgetCommand(widget, m_InPinningMode)); m_LastIntersectionTime = Time.realtimeSinceStartup; m_IntersectionThisFrame = true; // Pull/add from our cached list. WidgetManager.m_Instance.RefreshPinAndUnpinLists(); return(true); }
public HideWidgetCommand(GrabWidget widget, BaseCommand parent = null) : base(parent) { m_Widget = widget; if (widget is StencilWidget) { m_WidgetTransform = TrTransform.FromLocalTransform(widget.transform); } else if (widget is MediaWidget) { m_WidgetTransform = TrTransform.FromLocalTransform(widget.transform); m_WidgetTransform.scale = widget.GetSignedWidgetSize(); } m_TiltMeterCost = m_Widget.GetTiltMeterCost(); TiltMeterScript.m_Instance.AdjustMeterWithWidget(m_TiltMeterCost, up: false); }
public void OnWidgetRemovedFromGroup(GrabWidget widget, SketchGroupTag oldGroup) { // If the widget is in the selection, then we need to update our group to selected widget // mapping. if (m_SelectedWidgets.Contains(widget)) { RemoveFromGroupToSelectedWidgets(oldGroup, widget); } // Remove the widget from the old group to widgets mapping. if (oldGroup != SketchGroupTag.None) { // Remove this widget from the dictionary entry for the old group. m_GroupToWidgets[oldGroup].Remove(widget); } }
// Creates a new widget by instantiating the prefab and setting its transform. // spawnXf is in world space. public CreateWidgetCommand( GrabWidget widgetPrefab, TrTransform spawnXf, Quaternion?desiredEndForward = null, BaseCommand parent = null) : base(parent) { Transform controller = InputManager.m_Instance.GetController( InputManager.ControllerName.Brush).transform; m_Canvas = App.ActiveCanvas; m_SpawnXf = spawnXf; m_EndXf = TrTransform.TRS( Vector3.Lerp(m_SpawnXf.translation, controller.position, m_SpawnAggression), controller.rotation, m_SpawnXf.scale); m_Prefab = widgetPrefab; m_DesiredEndForward = desiredEndForward; }
/// Select a group that a widget belongs to and then return the corresponding selection widget. public SelectionWidget StartGrabbingGroupWithWidget(GrabWidget grabWidget) { m_IsGrabbingGroup = true; // Save off the current tool and selection. m_ToolTypeBeforeGrabbingGroup = SketchSurfacePanel.m_Instance.ActiveToolType; m_SelectedStrokesCopyWhileGrabbingGroup = new HashSet <Stroke>(m_SelectedStrokes); m_SelectedWidgetsCopyWhileGrabbingGroup = new HashSet <GrabWidget>(m_SelectedWidgets); // Select the group that the widget belongs to. ClearActiveSelection(); SketchMemoryScript.m_Instance.PerformAndRecordCommand( new SelectCommand(null, new[] { grabWidget }, SelectionTransform, deselect: false, initial: true, isGrabbingGroup: true)); UpdateSelectionWidget(); ResolveChanges(); SketchSurfacePanel.m_Instance.ActiveTool.HideTool(true); return(m_SelectionWidget); }
override protected bool HandleIntersectionWithWidget(GrabWidget widget) { // Can't select a pinned widget. if (widget.Pinned) { return(false); } var isSelected = SelectionManager.m_Instance.IsWidgetSelected(widget); bool removeFromSelection = SelectionManager.m_Instance.ShouldRemoveFromSelection(); if ((removeFromSelection && !isSelected) || (!removeFromSelection && isSelected)) { Debug.LogWarning( "Attempted to " + (removeFromSelection ? "deselect" : "select") + " a widget that's already " + (isSelected ? "selected" : "deselected") + "."); return(true); } PlayModifyStrokeSound(); SketchMemoryScript.m_Instance.PerformAndRecordCommand( new SelectCommand(null, new[] { widget }, SelectionManager.m_Instance.SelectionTransform, initial: !m_ActiveSelectionHasAtLeastOneObject, deselect: removeFromSelection)); m_ActiveSelectionHasAtLeastOneObject = true; m_LastIntersectionTime = Time.realtimeSinceStartup; // If we're selecting something while an existing selection has been transformed, // create a new selection and consolidate the command for selecting the future strokes // with the command to deselect the prior selection. if (!removeFromSelection && SelectionManager.m_Instance.SelectionWasTransformed) { EndSelection(); } return(true); }
public void OnWidgetAddedToGroup(GrabWidget widget) { SketchGroupTag newGroup = widget.Group; // If the widget is in the selection, then we need to update our group to selected widget // mapping. if (m_SelectedWidgets.Contains(widget)) { AddToGroupToSelectedWidgets(widget.Group, widget); } // Add the widget to the new group to widgets mapping. if (newGroup != SketchGroupTag.None) { // Add this widget to the dictionary entry for the new group. if (!m_GroupToWidgets.TryGetValue(newGroup, out var newGroupWidgets)) { newGroupWidgets = m_GroupToWidgets[newGroup] = new HashSet <GrabWidget>(); } newGroupWidgets.Add(widget); } }
override protected bool HandleIntersectionWithWidget(GrabWidget widget) { return(false); }
// ------------------------------------------------------------------------------------------ // // Private Internals // ------------------------------------------------------------------------------------------ // override protected void OnReadResults() { // Mark results as ready. m_ResultCount = 0; if (m_ResultList != null) { m_ResultList.Clear(); } uint[] resultColors = GetTextureColors(); // // Process the color buffer into result objects, if requested. // UnityEngine.Profiling.Profiler.BeginSample("Intersection: Process Results"); HashSet <object> seen = AllocateHashSet(); uint c; for (int i = 0; i < resultColors.Length; i++) { if (m_ResultCount == m_MaxResults) { break; } c = resultColors[i]; if (c > 0) { // Don't bother looking up the batch if the exact result set wasn't requested. if (m_ResultList == null) { m_ResultCount++; continue; } // TODO: the Color32 -> object lookup is deterministic and O(n), so 'seen' // should store the Color32, not the object. int triIndex = (int)(c & 0xffff) * 3; ushort batchId = (ushort)((c & 0xffff0000) >> 16); GrabWidget widget = null; Batch batch = null; BatchSubset subset = null; // See if this batch refers to a brush stroke. batch = App.ActiveCanvas.BatchManager.GetBatch(batchId); if (batch != null) { // TODO: move this into Batch, so can do binary search if necessary for (int j = 0; j < batch.m_Groups.Count; j++) { BatchSubset bs = batch.m_Groups[j]; if (triIndex >= bs.m_iTriIndex && triIndex < bs.m_iTriIndex + bs.m_nTriIndex) { subset = bs; break; } } // A stroke may be deleted by the time this executes. This is due to the delay between // sending an intersection request and processing the results. if (subset == null) { // This actually happens in practice! // TODO: investigate if it's okay // Debug.LogWarningFormat( // "Unexpected: Nonexistent subset for c = {0:x} {1:x}", // (ushort)(c >> 16), // (ushort)(c & 0xffff)); continue; } if (!seen.Add(subset)) { continue; } } else { // Not a brush stroke? See if this is a widget. widget = WidgetManager.m_Instance.GetBatch(batchId); // A widget may be deleted by the time this executes. This is due to the delay between // sending an intersection request and processing the results. if (widget == null) { continue; } if (!seen.Add(widget)) { continue; } } // A batch should never be null, but in the future that may change. This is possible due // to the delay between sending an intersection request and processing the results. if (batch == null && widget == null) { Debug.LogWarningFormat( "Unexpected: Null batch {0} and widget {1}", ReferenceEquals(batch, null), ReferenceEquals(widget, null)); continue; } // These cannot both be valid. Debug.Assert(subset == null || widget == null); m_ResultList.Add( new BatchResult { widget = widget, subset = subset }); m_ResultCount++; } } DeallocateHashSet(seen); UnityEngine.Profiling.Profiler.EndSample(); }
public PinWidgetCommand(GrabWidget widget, bool pin, BaseCommand parent = null) : base(parent) { m_Widget = widget; m_Pinning = pin; }
public bool IsWidgetSelected(GrabWidget widget) { return(m_SelectedWidgets.Contains(widget)); }
virtual protected bool HandleIntersectionWithWidget(GrabWidget widget) { return(true); }