Exemplo n.º 1
0
        public void MemorizeBrushStroke(
            BaseBrushScript brushScript, Color rColor, Guid brushGuid,
            float fBrushSize, float brushScale,
            List <PointerManager.ControlPoint> rControlPoints,
            StrokeFlags strokeFlags,
            StencilWidget stencil, float lineLength)
        {
            ClearRedo();

            Stroke rNewStroke = new Stroke();

            rNewStroke.m_Type                = Stroke.Type.BrushStroke;
            rNewStroke.m_Object              = brushScript.gameObject;
            rNewStroke.m_ControlPoints       = rControlPoints.ToArray();
            rNewStroke.m_ControlPointsToDrop = new bool[rNewStroke.m_ControlPoints.Length];
            rNewStroke.m_Color               = rColor;
            rNewStroke.m_BrushGuid           = brushGuid;
            rNewStroke.m_BrushSize           = fBrushSize;
            rNewStroke.m_BrushScale          = brushScale;
            rNewStroke.m_Flags               = strokeFlags;
            brushScript.Stroke               = rNewStroke;

            SketchMemoryScript.m_Instance.RecordCommand(
                new BrushStrokeCommand(rNewStroke, stencil, lineLength));

            MemoryListAdd(rNewStroke);

            TiltMeterScript.m_Instance.AdjustMeter(rNewStroke, up: true);
        }
Exemplo n.º 2
0
 private static string Compare(Mesh oldMesh, BaseBrushScript newBrush)
 {
     Vector3[] verts = oldMesh.vertices;
     int[]     tris  = oldMesh.triangles;
     // There is no way of querying Unity what the format of uv0 is, so don't check it
     return(Compare(verts, 0, verts.Length, tris, 0, tris.Length, null, newBrush));
 }
Exemplo n.º 3
0
  protected override void OnUndo() {
    AudioManager.m_Instance.PlayUndoSound(CommandAudioPosition);
    switch (m_Stroke.m_Type) {
    case Stroke.Type.BrushStroke: {
      GameObject gameObj = m_Stroke.m_Object;
      if (gameObj) {
        BaseBrushScript rBrushScript = gameObj.GetComponent<BaseBrushScript>();
        if (rBrushScript) {
          rBrushScript.HideBrush(true);
        }
      }
      break;
    }
    case Stroke.Type.BatchedBrushStroke: {
      var batch = m_Stroke.m_BatchSubset.m_ParentBatch;
      batch.DisableSubset(m_Stroke.m_BatchSubset);
      break;
    }
    case Stroke.Type.NotCreated:
      Debug.LogError("Unexpected: undo NotCreated stroke");
      break;
    }

    if (m_Widget != null) {
      m_Widget.AdjustLift(-m_LineLength_CS);
    }

    TiltMeterScript.m_Instance.AdjustMeter(m_Stroke, up: false);
  }
Exemplo n.º 4
0
  protected override void OnUndo() {
    SelectionManager.m_Instance.SelectionTransform = m_InitialSelectionTransform;
    if (m_Strokes != null) {
      for (int i = 0; i < m_Strokes.Length; ++i) {
        Stroke stroke = m_Strokes[i];
        switch (m_Strokes[i].m_Type) {
        case Stroke.Type.BrushStroke:
          BaseBrushScript rBrushScript = stroke.m_Object.GetComponent<BaseBrushScript>();
          if (rBrushScript) {
            rBrushScript.HideBrush(false);
          }
          break;
        case Stroke.Type.BatchedBrushStroke:
          stroke.m_BatchSubset.m_ParentBatch.EnableSubset(stroke.m_BatchSubset);
          break;
        case Stroke.Type.NotCreated:
          Debug.LogError("Unexpected: redo delete NotCreated stroke");
          break;
        }
        TiltMeterScript.m_Instance.AdjustMeter(stroke, up: true);
      }
    }
    if (m_Widgets != null) {
      for (int i = 0; i < m_Widgets.Count; ++i) {
        m_Widgets[i].RestoreFromToss();
      }
    }

    SelectionManager.m_Instance.RegisterStrokesInSelectionCanvas(m_Strokes);
    SelectionManager.m_Instance.RegisterWidgetsInSelectionCanvas(m_Widgets);
    SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.SelectionTool);
  }
Exemplo n.º 5
0
        /// Pass a Canvas parent, and a transform in that canvas's space.
        /// If overrideDesc passed, use that for the visuals -- m_CurrentBrush does not change.
        public void CreateNewLine(CanvasScript canvas, TrTransform xf_CS,
                                  ParametricStrokeCreator creator, BrushDescriptor overrideDesc = null)
        {
            // If straightedge is enabled, we may have a minimum size requirement.
            // Initialize parametric stroke creator for our type of straightedge.
            // Maybe change the brush to a proxy brush.
            BrushDescriptor desc = overrideDesc != null ? overrideDesc : m_CurrentBrush;

            m_CurrentCreator = creator;

            // Parametric creators want control over the brush size.
            if (m_CurrentCreator != null)
            {
                m_ParametricCreatorBackupStrokeSize = m_CurrentBrushSize;
                m_CurrentBrushSize = m_CurrentCreator.ProcessBrushSize(m_CurrentBrushSize);
            }

            m_LastUsedBrushSize_CS = (1 / Coords.CanvasPose.scale) * BrushSizeAbsolute;
            m_LineLength_CS        = 0.0f;

            float jitteredBrushSize = m_CurrentBrushSize;

            if (PointerManager.m_Instance.JitterEnabled)
            {
                jitteredBrushSize = PointerManager.m_Instance.GenerateJitteredSize(desc, m_CurrentBrushSize);
            }

            m_CurrentLine = BaseBrushScript.Create(
                canvas.transform, xf_CS,
                desc, m_CurrentColor, jitteredBrushSize);
        }
Exemplo n.º 6
0
        // Finishes initializing the passed PbChild, and adds to children array
        protected void InitializeAndAddChild(
            PbChild child,
            BrushDescriptor desc, Color color, float relativeSize = 1)
        {
            Debug.Assert(child.m_brush == null);
            TrTransform     childXf = child.CalculateChildXfFixedScale(m_knots);
            BaseBrushScript brush   = Create(
                transform.parent, childXf, desc, color, m_BaseSize_PS * relativeSize);
            ParentBrush pb = brush as ParentBrush;

            string originalName = brush.gameObject.name;
            string newName;

            if (pb != null)
            {
                newName = string.Format("{0}.{1}", gameObject.name, m_children.Count);
            }
            else
            {
                newName = string.Format(
                    "{0}.{1} (Leaf {2})", gameObject.name, m_children.Count, originalName);
            }
            brush.gameObject.name = newName;

            if (pb != null)
            {
                pb.m_recursionLevel = m_recursionLevel + 1;
            }

            child.m_brush = brush;
            m_children.Add(child);
        }
Exemplo n.º 7
0
  protected override void OnRedo() {
    SelectionManager.m_Instance.SelectionTransform = TrTransform.identity;
    if (m_Strokes != null) {
      for (int i = 0; i < m_Strokes.Length; ++i) {
        Stroke stroke = m_Strokes[i];
        switch (m_Strokes[i].m_Type) {
        case Stroke.Type.BrushStroke:
          BaseBrushScript rBrushScript = stroke.m_Object.GetComponent<BaseBrushScript>();
          if (rBrushScript) {
            rBrushScript.HideBrush(true);
          }
          break;
        case Stroke.Type.BatchedBrushStroke:
          stroke.m_BatchSubset.m_ParentBatch.DisableSubset(stroke.m_BatchSubset);
          break;
        case Stroke.Type.NotCreated:
          Debug.LogError("Unexpected: redo delete NotCreated stroke");
          break;
        }
        TiltMeterScript.m_Instance.AdjustMeter(stroke, up: false);
      }
    }
    if (m_Widgets != null) {
      for (int i = 0; i < m_Widgets.Count; ++i) {
        m_Widgets[i].Hide();
      }
    }

    SelectionManager.m_Instance.DeregisterStrokesInSelectionCanvas(m_Strokes);
    SelectionManager.m_Instance.DeregisterWidgetsInSelectionCanvas(m_Widgets);
  }
Exemplo n.º 8
0
        void CreatePreviewLine()
        {
            UnityEngine.Profiling.Profiler.BeginSample("PointerScript.CreatePreviewLine");
            if (m_PreviewLine == null && m_CurrentBrush.m_BrushPrefab != null)
            {
                // We don't have the transform for the line because it hasn't been created
                // yet, but we can assume that the line transform == the canvas transform,
                // since the line is parented to the canvas with an identity local transform.
                // See also the TODO in GetTransformForLine; fixing that will resolve this wart.
                Transform       notReallyTheLineTransformButCloseEnough = App.Instance.m_CanvasTransform;
                TrTransform     xf_LS = GetTransformForLine(notReallyTheLineTransformButCloseEnough);
                BaseBrushScript line  = BaseBrushScript.Create(
                    App.Instance.m_CanvasTransform,
                    xf_LS,
                    m_CurrentBrush, m_CurrentColor, m_CurrentBrushSize);

                line.gameObject.name = string.Format("Preview {0}", m_CurrentBrush.m_Description);
                line.SetPreviewMode();

                m_PreviewLine = line;
                ResetPreviewProperties();

                m_PreviewControlPoints.Clear();
            }
            UnityEngine.Profiling.Profiler.EndSample();
        }
Exemplo n.º 9
0
        /// Creates and returns a BatchSubset in the passed Canvas.
        /// If stroke contains too many CPs to fit, it will be cut short.
        /// This differs from what TB does, which is to create multiple subsets.
        public static BatchSubset CreateSubsetFromStroke(CanvasScript canvas, Stroke stroke)
        {
            // See PointerScript.RecreateLineFromMemory

            BrushDescriptor desc = BrushCatalog.m_Instance.GetBrush(stroke.m_BrushGuid);

            var             cp0 = stroke.m_ControlPoints[0];
            var             xf0 = TrTransform.TRS(cp0.m_Pos, cp0.m_Orient, stroke.m_BrushScale);
            BaseBrushScript bbs = BaseBrushScript.Create(
                canvas.transform, xf0, desc, stroke.m_Color, stroke.m_BrushSize);

            try {
                bbs.SetIsLoading();
                Assert.True(bbs.Canvas != null);

                foreach (var cp in stroke.m_ControlPoints)
                {
                    bbs.UpdatePosition_LS(
                        TrTransform.TRS(cp.m_Pos, cp.m_Orient, stroke.m_BrushScale), cp.m_Pressure);
                }
                return(bbs.FinalizeBatchedBrush());
            } finally {
                UnityEngine.Object.DestroyImmediate(bbs.gameObject);
            }
        }
Exemplo n.º 10
0
        protected override void OnUndo()
        {
            if (!m_SilenceFirstAudio)
            {
                AudioManager.m_Instance.PlayRedoSound(CommandAudioPosition);
            }
            m_SilenceFirstAudio = false;

            switch (m_TargetStroke.m_Type)
            {
            case Stroke.Type.BrushStroke:
                BaseBrushScript rBrushScript = m_TargetStroke.m_Object.GetComponent <BaseBrushScript>();
                if (rBrushScript)
                {
                    rBrushScript.HideBrush(false);
                }
                break;

            case Stroke.Type.BatchedBrushStroke:
                m_TargetStroke.m_BatchSubset.m_ParentBatch.EnableSubset(m_TargetStroke.m_BatchSubset);
                break;

            case Stroke.Type.NotCreated:
                Debug.LogError("Unexpected: undo delete NotCreated stroke");
                break;
            }

            TiltMeterScript.m_Instance.AdjustMeter(m_TargetStroke, up: true);
        }
Exemplo n.º 11
0
        /// Will flag a control point to keep, and a control point in the specified direction that is
        /// greater than the 'spawn interval' away.
        private void SavePointSequence(Stroke stroke, bool[] toDrop, int point,
                                       int dir, BaseBrushScript brushScript)
        {
            int count = (dir == 1) ? brushScript.Descriptor.m_HeadMinPoints
                : brushScript.Descriptor.m_TailMinPoints;
            int step = (dir == 1)
                ? brushScript.Descriptor.m_HeadPointStep
                : brushScript.Descriptor.m_TailPointStep;
            int lastPoint = point;

            toDrop[point] = false;
            float spawnInterval = brushScript.GetSpawnInterval(stroke.m_ControlPoints[point].m_Pressure);
            float sqrMinDist    = spawnInterval * spawnInterval;

            for (int i = point + dir; i < stroke.m_ControlPoints.Length && i >= 0; i += dir)
            {
                Vector3 diff = stroke.m_ControlPoints[i].m_Pos - stroke.m_ControlPoints[lastPoint].m_Pos;
                if (count % step == 0)
                {
                    toDrop[i] = false;
                }
                if (diff.sqrMagnitude >= sqrMinDist)
                {
                    if (--count <= 0)
                    {
                        return;
                    }
                    lastPoint = i;
                }
            }
            toDrop[point + dir] = false;
        }
Exemplo n.º 12
0
        private void FlagPointsToKeep(Stroke stroke, bool[] toDrop,
                                      BaseBrushScript brushScript)
        {
            if (stroke.m_ControlPoints.Length < 2)
            {
                return;
            }
            Vector3 lastDiff = stroke.m_ControlPoints[1].m_Pos - stroke.m_ControlPoints[0].m_Pos;

            for (int i = 1; i < stroke.m_ControlPoints.Length - 2; ++i)
            {
                Vector3 nextDiff = stroke.m_ControlPoints[i + 1].m_Pos - stroke.m_ControlPoints[i].m_Pos;
                if (Vector3.Dot(lastDiff, nextDiff) < 0)
                {
                    SavePointSequence(stroke, toDrop, i, -1, brushScript);
                    SavePointSequence(stroke, toDrop, i, 1, brushScript);
                }
                lastDiff = nextDiff;
            }

            if (brushScript.Descriptor.m_MiddlePointStep != 0)
            {
                for (int i = 0; i < stroke.m_ControlPointsToDrop.Length;
                     i += brushScript.Descriptor.m_MiddlePointStep)
                {
                    stroke.m_ControlPointsToDrop[i] = false;
                }
            }

            SavePointSequence(stroke, toDrop, 0, 1, brushScript);
            SavePointSequence(stroke, toDrop, stroke.m_ControlPoints.Length - 1, -1, brushScript);
        }
Exemplo n.º 13
0
 void OnDestroy()
 {
     foreach (var child in m_children)
     {
         BaseBrushScript bbs = child.m_brush;
         bbs.DestroyMesh();
         Destroy(bbs.gameObject);
     }
 }
Exemplo n.º 14
0
 public void DisablePreviewLine()
 {
     if (m_PreviewLine)
     {
         // TODO: Remove this (and other) calls to DestroyMesh() and do it inside OnDestroy() instead?
         m_PreviewLine.DestroyMesh();
         Destroy(m_PreviewLine.gameObject);
         m_PreviewLine = null;
     }
 }
Exemplo n.º 15
0
 public void CalculatePointsToDrop(Stroke stroke, BaseBrushScript brushScript) {
   if (!brushScript.Descriptor.m_SupportsSimplification) {
     return;
   }
   float sqrMaxError = Mathf.Pow(stroke.m_BrushScale * Level * 0.001f, 2f);
   if (stroke.m_ControlPoints.Length >= 4) {
     FlagPointsToDrop(stroke.m_ControlPoints, stroke.m_ControlPointsToDrop, 0,
       stroke.m_ControlPoints.Length - 1, sqrMaxError);
     FlagPointsToKeep(stroke, stroke.m_ControlPointsToDrop, brushScript);
   }
 }
Exemplo n.º 16
0
        protected override void OnRedo()
        {
            // Deselect selected strokes.
            if (m_SelectedStrokes != null)
            {
                SelectionManager.m_Instance.DeselectStrokes(m_SelectedStrokes);
            }
            // Deselect selected widgets.
            if (m_SelectedWidgets != null)
            {
                SelectionManager.m_Instance.DeselectWidgets(m_SelectedWidgets);
            }

            // Place duplicated strokes.
            foreach (var stroke in m_DuplicatedStrokes)
            {
                switch (stroke.m_Type)
                {
                case Stroke.Type.BrushStroke:
                {
                    BaseBrushScript brushScript = stroke.m_Object.GetComponent <BaseBrushScript>();
                    if (brushScript)
                    {
                        brushScript.HideBrush(false);
                    }
                }
                break;

                case Stroke.Type.BatchedBrushStroke:
                {
                    stroke.m_BatchSubset.m_ParentBatch.EnableSubset(stroke.m_BatchSubset);
                }
                break;

                default:
                    Debug.LogError("Unexpected: redo NotCreated duplicate stroke");
                    break;
                }
                TiltMeterScript.m_Instance.AdjustMeter(stroke, up: true);
            }
            SelectionManager.m_Instance.RegisterStrokesInSelectionCanvas(m_DuplicatedStrokes);

            // Place duplicated widgets.
            for (int i = 0; i < m_DuplicatedWidgets.Count; ++i)
            {
                m_DuplicatedWidgets[i].RestoreFromToss();
            }
            SelectionManager.m_Instance.RegisterWidgetsInSelectionCanvas(m_DuplicatedWidgets);

            // Set selection widget transforms.
            SelectionManager.m_Instance.SelectionTransform = m_DuplicateTransform;
            SelectionManager.m_Instance.UpdateSelectionWidget();
        }
Exemplo n.º 17
0
        /// Like BeginLineFromMemory + EndLineFromMemory
        /// To help catch bugs in higher-level stroke code, it is considered
        /// an error unless the stroke is in state NotCreated.
        public void RecreateLineFromMemory(Stroke stroke)
        {
            if (stroke.m_Type != Stroke.Type.NotCreated)
            {
                throw new InvalidOperationException();
            }
            if (BeginLineFromMemory(stroke, stroke.Canvas) == null)
            {
                // Unclear why it would have failed, but okay.
                // I guess we keep the old version?
                Debug.LogError("Unexpected error recreating line");
                return;
            }

            UpdateLineFromStroke(stroke);

            // It's kind of warty that this needs to happen; brushes should probably track
            // the mesh-dirty state and flush it in Finalize().
            // TODO: Check if this is still necessary now that QuadStripBrushStretchUV
            // flushes pending geometry changes in Finalize*Brush()
            m_CurrentLine.ApplyChangesToVisuals();

            // Copy in new contents

            if (App.Config.m_UseBatchedBrushes && m_CurrentLine.m_bCanBatch)
            {
                var subset = m_CurrentLine.FinalizeBatchedBrush();

                stroke.m_Type           = Stroke.Type.BatchedBrushStroke;
                stroke.m_IntendedCanvas = null;
                Debug.Assert(stroke.m_Object == null);
                stroke.m_BatchSubset          = subset;
                stroke.m_BatchSubset.m_Stroke = stroke;

                m_CurrentLine.DestroyMesh();
                Destroy(m_CurrentLine.gameObject);
            }
            else
            {
                m_CurrentLine.FinalizeSolitaryBrush();

                stroke.m_Type           = Stroke.Type.BrushStroke;
                stroke.m_IntendedCanvas = null;
                Debug.Assert(stroke.m_BatchSubset == null);
                stroke.m_Object = m_CurrentLine.gameObject;
                stroke.m_Object.GetComponent <BaseBrushScript>().Stroke = stroke;
            }

            m_CurrentLine = null;
        }
Exemplo n.º 18
0
        private void AdjustMeter(BatchSubset subset, float fBrushSize, bool bAddToMeter)
        {
            //make brush size not matter if we're ignorning it
            if (!m_BrushSizeAffectsCost)
            {
                fBrushSize = 1.0f;
            }

            //figure out how much this batch costs
            BrushDescriptor brush = BrushCatalog.m_Instance.GetBrush(
                subset.m_ParentBatch.ParentPool.m_BrushGuid);
            float fCost = BaseBrushScript.GetStrokeCost(brush, subset.m_VertLength, fBrushSize);

            AdjustMeter(bAddToMeter ? fCost : -fCost);
        }
Exemplo n.º 19
0
        public const float kPreviewDuration = 0.2f; // Must be > 0 for the particles shader to work.

        /// Creates and properly initializes a new line.
        /// Pass the initial transform in parent-local (Canvas) space.
        /// Pass the size in pointer (Room) space.
        public static BaseBrushScript Create(
            Transform parent,
            TrTransform xfInParentSpace,
            BrushDescriptor desc, Color color, float size_PS)
        {
            GameObject line = Instantiate(desc.m_BrushPrefab);

            line.transform.SetParent(parent);
            Coords.AsLocal[line.transform] = TrTransform.identity;
            line.name = desc.m_Description;

            BaseBrushScript currentLine = line.GetComponent <BaseBrushScript>();

            // TODO: pass this into InitBrush and do it there
            currentLine.m_Color       = color;
            currentLine.m_BaseSize_PS = size_PS;
            currentLine.InitBrush(desc, xfInParentSpace);
            return(currentLine);
        }
Exemplo n.º 20
0
        public static IEnumerable <Stroke> StrokesForTransforms(IEnumerable <Transform> transforms)
        {
            foreach (var t in transforms)
            {
                Batch batch = t.GetComponent <Batch>();
                if (batch != null)
                {
                    foreach (var group in batch.m_Groups)
                    {
                        yield return(group.m_Stroke);
                    }
                }

                BaseBrushScript brush = t.GetComponent <BaseBrushScript>();
                if (brush != null)
                {
                    yield return(brush.Stroke);
                }
            }
        }
Exemplo n.º 21
0
        private void AdjustMeter(GameObject rBrushStroke, float fBrushSize, bool bAddToMeter)
        {
            // Make brush size not matter if we're ignoring it
            if (!m_BrushSizeAffectsCost)
            {
                fBrushSize = 1.0f;
            }

            // If this brush stroke had a valid cost, adjust the meter
            BaseBrushScript rBrush = rBrushStroke.GetComponent <BaseBrushScript>();

            if (rBrush != null)
            {
                float fCost = BaseBrushScript.GetStrokeCost(
                    rBrush.Descriptor, rBrush.GetNumUsedVerts(), fBrushSize);
                if (fCost > 0.0f)
                {
                    AdjustMeter(bAddToMeter ? fCost : -fCost);
                }
            }
        }
Exemplo n.º 22
0
 public static void InitUndoObject(BaseBrushScript rBrushScript)
 {
     rBrushScript.CloneAsUndoObject();
 }
Exemplo n.º 23
0
        //
        // Sanity-checking geometry generation
        //

        // Return a non-null error message if the mesh data is not identical
        private static string Compare(
            Vector3[] oldVerts, int iOldVert0, int iOldVert1,
            int[]     oldTris, int iOldTri0, int iOldTri1,
            Vector2[] oldUv0s,
            BaseBrushScript newBrush)
        {
            Vector3[] newVerts; int nNewVerts;
            Vector2[] newUv0s;
            int[]     newTris; int nNewTris;
            newBrush.DebugGetGeometry(out newVerts, out nNewVerts, out newUv0s, out newTris, out nNewTris);

            if (nNewVerts != iOldVert1 - iOldVert0)
            {
                return("vert count mismatch");
            }

            for (int i = 0; i < nNewVerts; ++i)
            {
                Vector3 vo = oldVerts[iOldVert0 + i];
                Vector3 vn = newVerts[i];
                if (vo != vn)
                {
                    return(string.Format("vert mismatch @ {0}/{1}", i, nNewVerts));
                }
            }

            // Before enabling, we need a way of skipping this for brushes that
            // legitimately want randomized UVs. There is also a known nondeterminism
            // for QuadStripBrushStretchUV, though.
#if false
            if (oldUv0s != null)
            {
                if (newUv0s == null)
                {
                    return("uv0 mismatch (loaded mesh has no UVs)");
                }
                for (int i = 0; i < nNewVerts; ++i)
                {
                    Vector2 uvo = oldUv0s[iOldVert0 + i];
                    Vector2 uvn = newUv0s[i];
                    if (uvo != uvn)
                    {
                        return(string.Format("uv mismatch @ {0}/{1}", i, nNewVerts));
                    }
                }
            }
#endif

            if (nNewTris != iOldTri1 - iOldTri0)
            {
                return("tri count mismatch");
            }

            // Try to account for vert numbering
            {
                int triOffset = newTris[0] - oldTris[iOldTri0];
                for (int i = 0; i < nNewTris; ++i)
                {
                    int to = oldTris[iOldTri0 + i];
                    int tn = newTris[i];
                    if (to + triOffset != tn)
                    {
                        return(string.Format("tri mismatch @ {0}/{1}", i, nNewTris));
                    }
                }
            }
            return(null);
        }
Exemplo n.º 24
0
        void GetInfoFromSelection()
        {
            //don't start looking for a color until we're done with our selection
            Transform rCanvas = App.ActiveCanvas.transform;

            if (!m_SelectionInfoQueryComplete && (m_SelectionObjectIndex >= rCanvas.childCount))
            {
                int     iBestObject      = -1;
                float   fBestDistance    = 999999.0f;
                Vector3 vSelectionCenter = transform.position;
                float   fSelectionRadius = GetSize();
                for (int i = 0; i < m_CurrentSelection.Count; ++i)
                {
                    //don't try to get info from complex objects
                    SelectionObject rSelectedObject = m_CurrentSelection[i];
                    if (rSelectedObject.m_ComplexObject)
                    {
                        continue;
                    }

                    MeshFilter rMeshFilter        = rSelectedObject.m_Object.GetComponent <MeshFilter>();
                    Vector3    vTransformedCenter = rSelectedObject.m_Object.transform.InverseTransformPoint(vSelectionCenter);

                    //check each triangle for intersection
                    int       iMeshVertCount = rMeshFilter.mesh.vertexCount;
                    Vector3[] aVerts         = rMeshFilter.mesh.vertices;
                    Vector3[] aNorms         = rMeshFilter.mesh.normals;
                    for (int j = 0; j < iMeshVertCount; j += 3)
                    {
                        //check to see if we're within the sphere radius to the plane of this triangle
                        Vector3 vVert           = aVerts[j];
                        Vector3 vNorm           = aNorms[j];
                        float   fDistToPlane    = SignedDistancePlanePoint(ref vNorm, ref vVert, ref vTransformedCenter);
                        float   fAbsDistToPlane = Mathf.Abs(fDistToPlane);
                        if (fAbsDistToPlane < fSelectionRadius && fAbsDistToPlane < fBestDistance)
                        {
                            //we're within the radius to this triangle's plane, find the projected point
                            fDistToPlane *= -1.0f;
                            Vector3 vPlaneOffsetVector = vNorm * fDistToPlane;
                            Vector3 vPlaneIntersection = vTransformedCenter + vPlaneOffsetVector;

                            Vector3 vVert2 = aVerts[i + 1];
                            Vector3 vVert3 = aVerts[i + 2];

                            //walk the projected point toward the triangle center
                            Vector3 vTriCenter    = (vVert + vVert2 + vVert3) * 0.33333f;
                            Vector3 vToTriCenter  = vTriCenter - vPlaneIntersection;
                            float   fWalkDistance = Mathf.Min(vToTriCenter.magnitude, fSelectionRadius);
                            vToTriCenter.Normalize();
                            vToTriCenter       *= fWalkDistance;
                            vPlaneIntersection += vToTriCenter;

                            //see if this projected point is in the triangle
                            if (PointInTriangle(ref vPlaneIntersection, ref vVert, ref vVert2, ref vVert3))
                            {
                                //our projected point is in this triangle, store this distance as the best
                                iBestObject   = i;
                                fBestDistance = fDistToPlane;
                                break;
                            }
                        }
                    }
                }

                //this can happen if we don't have a selection
                if (iBestObject != -1)
                {
                    BaseBrushScript rBrushScript = m_CurrentSelection[iBestObject].m_Object.GetComponent <BaseBrushScript>();
                    if (rBrushScript)
                    {
                        m_SelectionColor     = rBrushScript.CurrentColor;
                        m_SelectionBrush     = rBrushScript.Descriptor;
                        m_SelectionInfoValid = true;
                    }
                }
                else
                {
                    m_SelectionColor = Color.white;
                    m_SelectionBrush = null;
                }

                m_SelectionInfoQueryComplete = true;
            }
        }
Exemplo n.º 25
0
        // During playback, rMemoryObjectForPlayback is non-null, and strokeFlags should not be passed.
        // otherwise, rMemoryObjectForPlayback is null, and strokeFlags should be valid.
        // When non-null, rMemoryObjectForPlayback corresponds to the current line.
        public void DetachLine(
            bool bDiscard,
            Stroke rMemoryObjectForPlayback,
            SketchMemoryScript.StrokeFlags strokeFlags = SketchMemoryScript.StrokeFlags.None)
        {
            if (ApiManager.Instance.HasOutgoingListeners)
            {
                var color           = App.BrushColor.CurrentColor;
                var pointsAsStrings = new List <string>();
                foreach (var cp in m_ControlPoints)
                {
                    var pos = cp.m_Pos;
                    var rot = cp.m_Orient.eulerAngles;
                    pointsAsStrings.Add($"[{pos.x},{pos.y},{pos.z},{rot.x},{rot.y},{rot.z},{cp.m_Pressure}]");
                }
                ApiManager.Instance.EnqueueOutgoingCommands(
                    new List <KeyValuePair <string, string> >
                {
                    new KeyValuePair <string, string>("brush.type", CurrentBrush.m_Guid.ToString()),
                    new KeyValuePair <string, string>("color.set.rgb", $"{color.r},{color.g},{color.b}"),
                    new KeyValuePair <string, string>("draw.stroke", string.Join(",", pointsAsStrings))
                }
                    );
            }

            if (rMemoryObjectForPlayback != null)
            {
                Debug.Assert(strokeFlags == SketchMemoryScript.StrokeFlags.None);
            }

            if (bDiscard)
            {
                m_CurrentLine.DestroyMesh();
                Destroy(m_CurrentLine.gameObject);
            }
            else if (App.Config.m_UseBatchedBrushes && m_CurrentLine.m_bCanBatch)
            {
                // Save line: batched case

                // ClearRedo() is called by MemorizeXxx(), but also do it earlier as a
                // fragmentation optimization; this allows GenerateBatchSubset() to reuse the
                // reclaimed space.
                // NB: batching currently handles fragmentation poorly, so consider this
                // optimization necessary.
                if (rMemoryObjectForPlayback == null)
                {
                    SketchMemoryScript.m_Instance.ClearRedo();
                }

                var subset = m_CurrentLine.FinalizeBatchedBrush();
                if (rMemoryObjectForPlayback == null)
                {
                    SketchMemoryScript.m_Instance.MemorizeBatchedBrushStroke(
                        subset, m_CurrentColor,
                        m_CurrentBrush.m_Guid,
                        m_CurrentBrushSize,
                        m_CurrentLine.StrokeScale,
                        m_ControlPoints, strokeFlags,
                        WidgetManager.m_Instance.ActiveStencil, m_LineLength_CS, m_CurrentLine.RandomSeed);
                }
                else
                {
                    //if we're in playback, patch up the in-memory stroke with its position in the batch
                    rMemoryObjectForPlayback.m_Type        = Stroke.Type.BatchedBrushStroke;
                    rMemoryObjectForPlayback.m_Object      = null;
                    rMemoryObjectForPlayback.m_BatchSubset = subset;
                    subset.m_Stroke = rMemoryObjectForPlayback;
                }

                //destroy original stroke, as it's now part of the batch stroke
                m_CurrentLine.DestroyMesh();
                Destroy(m_CurrentLine.gameObject);

                // recreate the stroke if it's just been drawn by the user, so we can run the simplifier on it.
                if (!App.Instance.IsLoading() &&
                    QualityControls.m_Instance.UserStrokeSimplifier.Level > 0.0f &&
                    m_CurrentLine.Descriptor.m_SupportsSimplification)
                {
                    var stroke = subset.m_Stroke;
                    stroke.InvalidateCopy();
                    stroke.Uncreate();
                    stroke.Recreate();
                }
            }
            else
            {
                // Save line: non-batched case

                if (rMemoryObjectForPlayback == null)
                {
                    SketchMemoryScript.m_Instance.MemorizeBrushStroke(
                        m_CurrentLine, m_CurrentColor,
                        m_CurrentBrush.m_Guid,
                        m_CurrentBrushSize,
                        m_CurrentLine.StrokeScale,
                        m_ControlPoints, strokeFlags,
                        WidgetManager.m_Instance.ActiveStencil, m_LineLength_CS);
                }
                else
                {
                    rMemoryObjectForPlayback.m_Type        = Stroke.Type.BrushStroke;
                    rMemoryObjectForPlayback.m_BatchSubset = null;
                    m_CurrentLine.Stroke = rMemoryObjectForPlayback;
                }

                //copy master brush over to current line
                m_CurrentLine.FinalizeSolitaryBrush();
            }

            if (rMemoryObjectForPlayback == null)
            {
                SilenceAudio();
            }

            m_CurrentLine = null;
            // Restore brush size if our parametric creator had to modify it.
            if (m_CurrentCreator != null)
            {
                m_CurrentBrushSize = m_ParametricCreatorBackupStrokeSize;
            }
            m_CurrentCreator = null;
            m_ControlPoints.Clear();
        }
Exemplo n.º 26
0
        // During playback, rMemoryObjectForPlayback is non-null, and strokeFlags should not be passed.
        // otherwise, rMemoryObjectForPlayback is null, and strokeFlags should be valid.
        // When non-null, rMemoryObjectForPlayback corresponds to the current line.
        public void DetachLine(
            bool bDiscard,
            Stroke rMemoryObjectForPlayback,
            SketchMemoryScript.StrokeFlags strokeFlags = SketchMemoryScript.StrokeFlags.None)
        {
            if (rMemoryObjectForPlayback != null)
            {
                Debug.Assert(strokeFlags == SketchMemoryScript.StrokeFlags.None);
            }

            if (bDiscard)
            {
                m_CurrentLine.DestroyMesh();
                Destroy(m_CurrentLine.gameObject);
            }
            else if (App.Config.m_UseBatchedBrushes && m_CurrentLine.m_bCanBatch)
            {
                // Save line: batched case

                // ClearRedo() is called by MemorizeXxx(), but also do it earlier as a
                // fragmentation optimization; this allows GenerateBatchSubset() to reuse the
                // reclaimed space.
                // NB: batching currently handles fragmentation poorly, so consider this
                // optimization necessary.
                if (rMemoryObjectForPlayback == null)
                {
                    SketchMemoryScript.m_Instance.ClearRedo();
                }

                var subset = m_CurrentLine.FinalizeBatchedBrush();
                if (rMemoryObjectForPlayback == null)
                {
                    SketchMemoryScript.m_Instance.MemorizeBatchedBrushStroke(
                        subset, m_CurrentColor,
                        m_CurrentBrush.m_Guid,
                        m_CurrentBrushSize,
                        m_CurrentLine.StrokeScale,
                        m_ControlPoints, strokeFlags,
                        WidgetManager.m_Instance.ActiveStencil, m_LineLength_CS, m_CurrentLine.RandomSeed);
                }
                else
                {
                    //if we're in playback, patch up the in-memory stroke with its position in the batch
                    rMemoryObjectForPlayback.m_Type        = Stroke.Type.BatchedBrushStroke;
                    rMemoryObjectForPlayback.m_Object      = null;
                    rMemoryObjectForPlayback.m_BatchSubset = subset;
                    subset.m_Stroke = rMemoryObjectForPlayback;
                }

                //destroy original stroke, as it's now part of the batch stroke
                m_CurrentLine.DestroyMesh();
                Destroy(m_CurrentLine.gameObject);

                // recreate the stroke if it's just been drawn by the user, so we can run the simplifier on it.
                if (!App.Instance.IsLoading() &&
                    QualityControls.m_Instance.UserStrokeSimplifier.Level > 0.0f &&
                    m_CurrentLine.Descriptor.m_SupportsSimplification)
                {
                    var stroke = subset.m_Stroke;
                    stroke.InvalidateCopy();
                    stroke.Uncreate();
                    stroke.Recreate();
                }
            }
            else
            {
                // Save line: non-batched case

                if (rMemoryObjectForPlayback == null)
                {
                    SketchMemoryScript.m_Instance.MemorizeBrushStroke(
                        m_CurrentLine, m_CurrentColor,
                        m_CurrentBrush.m_Guid,
                        m_CurrentBrushSize,
                        m_CurrentLine.StrokeScale,
                        m_ControlPoints, strokeFlags,
                        WidgetManager.m_Instance.ActiveStencil, m_LineLength_CS);
                }
                else
                {
                    rMemoryObjectForPlayback.m_Type        = Stroke.Type.BrushStroke;
                    rMemoryObjectForPlayback.m_BatchSubset = null;
                    m_CurrentLine.Stroke = rMemoryObjectForPlayback;
                }

                //copy master brush over to current line
                m_CurrentLine.FinalizeSolitaryBrush();
            }

            if (rMemoryObjectForPlayback == null)
            {
                SilenceAudio();
            }

            m_CurrentLine = null;
            // Restore brush size if our parametric creator had to modify it.
            if (m_CurrentCreator != null)
            {
                m_CurrentBrushSize = m_ParametricCreatorBackupStrokeSize;
            }
            m_CurrentCreator = null;
            m_ControlPoints.Clear();
        }