Author Topic: Transient code works in acad, not in bricscad  (Read 3194 times)

0 Members and 1 Guest are viewing this topic.

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Transient code works in acad, not in bricscad
« on: September 27, 2017, 04:43:32 PM »
I did a test prog to draw a fence on screen as the user picks.
It works fine in autocad, but not in bricscad v16. I will try on V17 soon.

Here is the code, very typical of example routines that use point monitor.
What you should get is a red polyline being drawn, just like drawing a real pline.
Escape kills it, this is just an example prog.

Code: [Select]
//C# Usings
using System;
using System.Collections;
using SC = System.Collections;
using System.Collections.Generic;
using SCG = System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using SWF = System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Xml;
using System.Xml.Serialization;
using SM = System.Math;
using System.Linq;

//AutoCad Usings
#if ACAD
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.EditorInput;
using AcEd = Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using AcGe = Autodesk.AutoCAD.Geometry;
using AcCo = Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.Windows;
using AcWn = Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Customization;
#endif
#if BCAD
using Teigha.DatabaseServices;
using AcDb = Teigha.DatabaseServices;
using Bricscad.EditorInput;
using AcEd = Bricscad.EditorInput;
using Teigha.Geometry;
using AcGe = Teigha.Geometry;
using AcCo = Teigha.Colors;
using Teigha.Runtime;
using Teigha.GraphicsInterface;
using Bricscad.Runtime;
using Bricscad.ApplicationServices;
using AcAp = Bricscad.ApplicationServices.Application;
using Bricscad.Windows;
using AcWn = Bricscad.Windows;
#endif


[assembly: CommandClass(typeof(ProgTestingAcad.Program2))]

namespace ProgTestingAcad {

    public class Program2 {

        [CommandMethod("TESTPTS2")]
        public static void GetPts() {
            Document dwg = AcAp.DocumentManager.MdiActiveDocument;
            Editor ed = dwg.Editor;

            MyptCmd cmd = new MyptCmd(dwg);
            cmd.GetPts();
        }
    }

    public class MyptCmd {
        private Document _dwg;
        private Editor _editor;

        private List<Point2d> _points;
        private List<Point2d> _origpoints = new List<Point2d>();
        private Point2d _resPt;
        private AcDb.Polyline _pline = null;

        public MyptCmd(Document dwg) {
            _dwg = dwg;
            _editor = _dwg.Editor;
        }

        public void GetPts() {

            _points = new List<Point2d>();

            //get first point
            PromptPointOptions opt = new PromptPointOptions("\nPick Point: ");
            PromptPointResult res = _editor.GetPoint(opt);
            if (res.Status == PromptStatus.OK) {
                _origpoints.Add(new AcGe.Point2d(res.Value.X, res.Value.Y));

                try {
                    //Handling mouse cursor moving during picking
                    _editor.PointMonitor += new PointMonitorEventHandler(_editor_PointMonitor);

                    bool loop = true;
                    //get more points
                    while (loop) {
                        if (!PickNewPoint())
                            loop = false; //no point
                        else
                            _origpoints.Add(_resPt);
                    }
                }
                catch {
                    throw;
                }
                finally {
                    ClearTransientGraphics();
                    //Remove PointMonitor handler
                    _editor.PointMonitor -= new PointMonitorEventHandler(_editor_PointMonitor);
                }
            }
        }

        private bool PickNewPoint() {
            PromptPointOptions opt = new PromptPointOptions("\nPick Point: ");
            PromptPointResult res = _editor.GetPoint(opt);

            if (res.Status == PromptStatus.OK) {
                _resPt = new AcGe.Point2d(res.Value.X, res.Value.Y);
                return true;
            }
            else {
                return false;
            }
        }

        private void ClearTransientGraphics() {
            TransientManager.CurrentTransientManager.EraseTransients(
                TransientDrawingMode.DirectShortTerm,
                128, new IntegerCollection());
            if (_pline != null)
                _pline.Dispose();
            _pline = null;
        }

        private void _editor_PointMonitor(object sender, PointMonitorEventArgs e) {
            ClearTransientGraphics();
            Point2d pt = new Point2d(e.Context.RawPoint.X, e.Context.RawPoint.Y);
            bool go = true;

            //figure new points
            //set _points to orig and add point
            //we must do this as we cannot simply add a point
            _points = new List<Point2d>();
            _points.AddRange(_origpoints);
            _points.Add(pt);

            //draw new _pline
            if (go) {
                _pline = new AcDb.Polyline(_points.Count);
                for (int i = 0; i < _points.Count; i++) {
                    _pline.AddVertexAt(i, _points[i], 0.0, 0.0, 0.0);
                }
                _pline.ColorIndex = 1;
                TransientManager.CurrentTransientManager.AddTransient(
                    _pline, TransientDrawingMode.DirectShortTerm, 128
                    , new IntegerCollection());
            }
        }

    }
}

Any ideas?
I tried directTopMost and other ideas, that did not matter.
thx
James Maeding

huiz

  • Swamp Rat
  • Posts: 917
  • Certified Prof C3D
Re: Transient code works in acad, not in bricscad
« Reply #1 on: September 27, 2017, 05:09:44 PM »
I noticed BricsCAD V17 does not update a transient entity during a PointMonitor, unless you scroll the mousewheel. Just static transient entities works fine.

The programmers in Gent are aware of it and will examine the possibilities.
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Transient code works in acad, not in bricscad
« Reply #2 on: September 27, 2017, 05:32:15 PM »
Nooooooooooooooo........
Shoot, I hit a bug?
I did a ton of programming in acad and have tried transients in bcad before so never thought they would misbehave in pointmonitor.
I hope they fix this.

Thanks for the heads up huiz!
James Maeding

huiz

  • Swamp Rat
  • Posts: 917
  • Certified Prof C3D
Re: Transient code works in acad, not in bricscad
« Reply #3 on: September 28, 2017, 03:57:12 AM »
At least they take it more serious than another CAD software company  ;D
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8690
  • AKA Daniel
Re: Transient code works in acad, not in bricscad
« Reply #4 on: September 28, 2017, 09:45:07 AM »
hack alert
Code - C++: [Select]
  1.             if (go)
  2.             {
  3.                 _pline = new AcDb.Polyline(_points.Count);
  4.                 for (int i = 0; i < _points.Count; i++)
  5.                 {
  6.                     _pline.AddVertexAt(i, _points[i], 0.0, 0.0, 0.0);
  7.                 }
  8.                 _pline.ColorIndex = 1;
  9.                 TransientManager.CurrentTransientManager.AddTransient(
  10.                     _pline, TransientDrawingMode.DirectShortTerm, 128
  11.                     , new IntegerCollection());
  12.  
  13.                 _editor.SetCurrentView(_editor.GetCurrentView());//<<<----
  14.             }
  15.  

edit: needs to be disposed so..

Code - C++: [Select]
  1.                using (ViewTableRecord rec = _editor.GetCurrentView())
  2.                 {
  3.                     _editor.SetCurrentView(rec);
  4.                 }
  5.  

there is probably a better alternative, this seems slightly laggy on large drawings


« Last Edit: September 28, 2017, 06:13:10 PM by nullptr »

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Transient code works in acad, not in bricscad
« Reply #5 on: September 28, 2017, 01:28:26 PM »
'That is really amazing.' .... 'That really is truly amazing. That is so amazingly amazing I think I'd like to steal it.' -Zaphod Beeblebrox

It works, that was too easy! Thanks a TON for your reply, now my Bricscad stuff works perfect, I owe you!
James Maeding

huiz

  • Swamp Rat
  • Posts: 917
  • Certified Prof C3D
Re: Transient code works in acad, not in bricscad
« Reply #6 on: October 03, 2017, 07:51:03 AM »
Indeed, perfect! In the AutoCAD variant I did not set the Current View, it works fine that way. If I add the SetCurrentView to the code it works as well in BricsCAD in a PointMonitor!

Sorry James that I incorrectly informed you, I was not aware of the brilliant solution!  :mrgreen:
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Transient code works in acad, not in bricscad
« Reply #7 on: October 03, 2017, 11:07:38 AM »
Huiz, you were right that bricsys is working on it, they told me also.
I also added a #if BCAD...statement to just run for bcad.

The use of transients like this is going to change so many tools I have done.
I used to use grdraw but that is archaic compared to transients.
James Maeding

Atook

  • Swamp Rat
  • Posts: 1029
  • AKA Tim
Re: Transient code works in acad, not in bricscad
« Reply #8 on: October 25, 2017, 11:41:34 PM »
Thanks for the workaround Daniel. Worked a treat here as well.

FYI as of Bricscad V18.1.02 beta, transients are still borked and need the .SetCurrentView call to show up.
« Last Edit: October 25, 2017, 11:46:32 PM by Atook »

Danipon

  • Mosquito
  • Posts: 5
Re: Transient code works in acad, not in bricscad
« Reply #9 on: January 01, 2018, 11:38:27 AM »
Just for fun refactored the code to show the UpdateTransient method.
C#-VS2017 Default. Tested in A2018 and B18. Daniel workaround confirmed. Code working in 2D only. Forgive namespace.

Code - C#: [Select]
  1. using System;
  2. using System.Collections.Generic;
  3.  
  4.  
  5. #if ACAD
  6. using Autodesk.AutoCAD.ApplicationServices;
  7. using Autodesk.AutoCAD.EditorInput;
  8. using Autodesk.AutoCAD.Geometry;
  9. using Autodesk.AutoCAD.GraphicsInterface;
  10. using DbPolyline = Autodesk.AutoCAD.DatabaseServices.Polyline;
  11. #elif BCAD
  12. using Bricscad.ApplicationServices;
  13. using Bricscad.EditorInput;
  14. using Teigha.Geometry;
  15. using Teigha.GraphicsInterface;
  16. using DbPolyline = Teigha.DatabaseServices.Polyline;
  17. #endif
  18.  
  19.  
  20. namespace TopMecNet.Experimental
  21. {
  22.     public class PointsPicker
  23.     {
  24.         private readonly Editor _editor;
  25.        
  26.         private List<Point2d> _pickedPoints;
  27.  
  28.         private Point2d _pickedPoint;
  29.  
  30.         private DbPolyline _pline;
  31.  
  32.         private bool _pointPicked;
  33.  
  34.  
  35.         public PointsPicker(Document dwg)
  36.         {
  37.             _editor = dwg.Editor;
  38.         }
  39.  
  40.         public List<Point2d> PickedPoints
  41.         {
  42.             get { return _pickedPoints; }
  43.         }
  44.  
  45.         public void PickPoints()
  46.         {
  47.             _pickedPoints = new List<Point2d>();
  48.  
  49.             // get first point
  50.             var opt = new PromptPointOptions("\nPick Point: ");
  51.             var res = _editor.GetPoint(opt);
  52.  
  53.             if (res.Status != PromptStatus.OK)
  54.                 return;
  55.  
  56.             _pickedPoint = new Point2d(res.Value.X, res.Value.Y);
  57.             PickedPoints.Add(_pickedPoint);
  58.             _pointPicked = true;
  59.  
  60.             try
  61.             {
  62.                 CreateTransientGraphics();
  63.  
  64.                 // handling mouse cursor moving during picking
  65.                 _editor.PointMonitor += _editor_PointMonitor;
  66.  
  67.                 // get more points
  68.                 while (PickNewPoint())
  69.                 {
  70.                     PickedPoints.Add(_pickedPoint);
  71.                     _pointPicked = true;
  72.                 }
  73.  
  74.             }
  75.             catch(Exception ex)
  76.             {
  77.                 _editor.WriteMessage(ex.Message);
  78.             }
  79.             finally
  80.             {
  81.                 ClearTransientGraphics();
  82.  
  83.                 // remove PointMonitor handler
  84.                 _editor.PointMonitor -= _editor_PointMonitor;
  85.             }
  86.         }
  87.  
  88.         private bool PickNewPoint()
  89.         {
  90.             var opt = new PromptPointOptions("\nPick Point: ") {AllowNone = true};
  91.             var res = _editor.GetPoint(opt);
  92.  
  93.             if (res.Status != PromptStatus.OK)
  94.                 return false;
  95.  
  96.             _pickedPoint = new Point2d(res.Value.X, res.Value.Y);
  97.             return true;
  98.         }
  99.  
  100.  
  101.         private void CreateTransientGraphics()
  102.         {
  103.             _pline = new DbPolyline(0) {ColorIndex = 1};
  104.            
  105.             TransientManager.CurrentTransientManager.AddTransient(
  106.                 _pline, TransientDrawingMode.DirectShortTerm, 128
  107.                 , new IntegerCollection());
  108.         }
  109.  
  110.         private void ClearTransientGraphics()
  111.         {
  112.             TransientManager.CurrentTransientManager.EraseTransients(TransientDrawingMode.DirectShortTerm,
  113.                 128, new IntegerCollection());
  114.  
  115.             if (_pline != null)
  116.                 _pline.Dispose();
  117.  
  118.             _pline = null;
  119.         }
  120.  
  121.         private void UpdateTransientGraphics(Point2d dragVertex)
  122.         {
  123.             if (_pointPicked)
  124.             {
  125.                 // add the picked vertex
  126.                 _pline.AddVertexAt(_pline.NumberOfVertices, _pickedPoint, 0.0, 0.0, 0.0);
  127.                 // add the dragging vertex
  128.                 _pline.AddVertexAt(_pline.NumberOfVertices, dragVertex, 0.0, 0.0, 0.0);
  129.             }
  130.             else
  131.             {
  132.                 // update the last vertex
  133.                 _pline.SetPointAt(_pline.NumberOfVertices - 1, dragVertex);
  134.             }
  135.  
  136.             TransientManager.CurrentTransientManager.UpdateTransient(_pline, new IntegerCollection());
  137.  
  138.             // wake up BricsCAD
  139.             using (var rec = _editor.GetCurrentView())
  140.                 _editor.SetCurrentView(rec);
  141.  
  142.             _pointPicked = false;
  143.         }
  144.  
  145.        
  146.  
  147.         private void _editor_PointMonitor(object sender, PointMonitorEventArgs e)
  148.         {
  149.             // simulate next vertex
  150.             UpdateTransientGraphics(new Point2d(e.Context.RawPoint.X, e.Context.RawPoint.Y));
  151.         }
  152.  
  153.     }
  154.  
  155.     /// <summary>
  156.     /// Class TestPickPoints. ATTACH COMMAND HERE.
  157.     /// </summary>
  158.     public static class TestPickPoints
  159.     {
  160.         public static void Test()
  161.         {
  162.             var dwg = Application.DocumentManager.MdiActiveDocument;
  163.            
  164.             var pointsPicker = new PointsPicker(dwg);
  165.             pointsPicker.PickPoints();
  166.             var points = pointsPicker.PickedPoints;
  167.            
  168.             Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("Picked {0} points.", points.Count));
  169.         }
  170.     }
  171.  
  172. }
  173.