Author Topic: Help with reactor  (Read 4902 times)

0 Members and 1 Guest are viewing this topic.

Coder

  • Swamp Rat
  • Posts: 827
Help with reactor
« on: July 31, 2014, 02:16:37 PM »
Hello guys .

I am trying to write a reactor to not allow any changes on a text I insert and re write it if modified .

Code: [Select]
(defun c:write (/ pnt txtobj)
  (vl-load-com)
     (setq pnt (getpoint "\n text location :"))
      (setq txtobj (entmakex (list '(0 . "TEXT")
                              (cons 10 pnt)
                              (cons 11 pnt)
                              (cons 40 1.0)
                              (cons 1 "Text example")
                        )
              )
      )
      (setq *obj* (vlr-object-reactor
                    (list (vlax-ename->vla-object txtobj))
                    "example-1"
                    '((:vlr-modified . modifytext))
                  )
      )
  (princ)
)

(defun modifytext (noifier reactor paparms /)
  (vla-put-textstring (vlr-data reactor) "Text example")
)

thanks in advance . :)

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: Help with reactor
« Reply #1 on: July 31, 2014, 04:47:21 PM »
As noted in the developers documentation for reactors, trying to modify the entity you are reacting to is a Bad Thing To Do.   :police:
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Help with reactor
« Reply #2 on: August 01, 2014, 04:29:19 AM »
Note that (vlr-data reactor) does not point to the text object.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Help with reactor
« Reply #3 on: August 12, 2014, 04:12:45 AM »
A way around the limitation referred to by dgorsman is to use an acdb reactor instead of an object reactor.

It is important to realise that an acdb reactor will react to every change to the database so you need some condition inside the callback function to limit actions to certain cases.

But there are other, easier, ways to 'protect' a text entity that do not rely on Lisp code and reactors. I am thinking of a locked layer or putting the entity in a non-explodable block.

Note: The code was only tested BricsCAD.

Code: [Select]
(defun c:write (/ pnt enameTxt)
  (vl-load-com)
  (setq pnt (getpoint "\nText location: "))
  (setq enameTxt
    (entmakex
      (list
        '(0 . "TEXT")
        (cons 10 pnt)
        (cons 11 pnt)
        (cons 40 1.0)
        (cons 1 "Text example")
      )
    )
  )
  (setq *acdbReactor*
    (vlr-acdb-reactor
      enameTxt ; Reactor data.
      '((:vlr-objectmodified . CallBackObjectModified))
    )
  )
  (princ)
)

(defun CallBackObjectModified (rea lst)
  (print "> CallBackObjectModified")
  (if
    (and
      (equal (cadr lst) (vlr-data rea))
      (vlax-write-enabled-p (cadr lst))
    )
    (progn
      (print "> CallBackObjectModified > Action")
      (vla-put-textstring (vlax-ename->vla-object (cadr lst)) "Text example")
    )
  )
)

Coder

  • Swamp Rat
  • Posts: 827
Re: Help with reactor
« Reply #4 on: August 12, 2014, 01:36:06 PM »
Thank you roy so much .

The routine does not reset the text if it is modified  :embarrassed:

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Help with reactor
« Reply #5 on: August 13, 2014, 03:36:08 AM »
Thank you roy so much .

The routine does not reset the text if it is modified  :embarrassed:
The code then only works on BricsCAD and not on AutoCAD. :-(

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Help with reactor
« Reply #6 on: August 13, 2014, 05:57:07 AM »
Maybe using (vla-sendcommand) and a 'PostProcess' will work on AutoCAD? The code below works fine on BricsCAD.
Code: [Select]
(defun c:write (/ pnt enameTxt)
  (vl-load-com)
  (setq pnt (getpoint "\nText location: "))
  (setq enameTxt
    (entmakex
      (list
        '(0 . "TEXT")
        (cons 10 pnt)
        (cons 11 pnt)
        (cons 40 1.0)
        (cons 1 "Text example")
      )
    )
  )
  (setq *acdbReactor*
    (vlr-acdb-reactor
      enameTxt ; Reactor data.
      '((:vlr-objectmodified . CallBackObjectModified))
    )
  )
  (princ)
)

(defun CallBackObjectModified (rea lst /)
  (print "> CallBackObjectModified")
  (if (equal (cadr lst) (vlr-data rea))
    (progn
      (print "> CallBackObjectModified > Action: Send command")
      (vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) "(PostProcess) ")
    )
  )
)

(defun PostProcess ( / enameTxt)
  (print "> PostProcess")
  (if (not (vlax-erased-p (setq enameText (vlr-data *acdbReactor*))))
    (progn
      (print "> PostProcess > Action")
      (vla-put-textstring (vlax-ename->vla-object enameText) "Text example")
    )
  )
  (princ)
)

tombu

  • Bull Frog
  • Posts: 289
  • ByLayer=>Not0
Re: Help with reactor
« Reply #7 on: August 13, 2014, 07:16:28 AM »
Plot the text to PDF and attach it to the drawing. 
Tom Beauford P.S.M.
Leon County FL Public Works - Windows 7 64 bit AutoCAD Civil 3D

Coder

  • Swamp Rat
  • Posts: 827
Re: Help with reactor
« Reply #8 on: August 13, 2014, 11:06:30 AM »
Maybe using (vla-sendcommand) and a 'PostProcess' will work on AutoCAD? The code below works fine on BricsCAD.

Thank you roy for your help , that is too kind work from you .  :-)

Your codes work but it keeps printing in the command line too much until I press esc button to stop .

Quote
Select an annotation object or [Undo]: (PostProcess)
"> PostProcess"
"> PostProcess > Action"
"> CallBackObjectModified"
"> CallBackObjectModified > Action: Send command"

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Help with reactor
« Reply #9 on: August 14, 2014, 03:13:48 AM »
OK, so obviously a global variable is required to avoid a chain reaction on AutoCAD.
Code: [Select]
(defun c:write (/ pnt enameTxt)
  (vl-load-com)
  (setq pnt (getpoint "\nText location: "))
  (setq enameTxt
    (entmakex
      (list
        '(0 . "TEXT")
        (cons 10 pnt)
        (cons 11 pnt)
        (cons 40 1.0)
        (cons 1 "Text example")
      )
    )
  )
  (setq *acdbReactor*
    (vlr-acdb-reactor
      enameTxt ; Reactor data.
      '((:vlr-objectmodified . CallBackObjectModified))
    )
  )
  (princ)
)

(defun CallBackObjectModified (rea lst /)
  (print "> CallBackObjectModified")
  (if
    (and
      (not *waitingForPostProcessP*)
      (equal (cadr lst) (vlr-data rea))
    )
    (progn
      (print "> CallBackObjectModified > Action: Send command")
      (setq *waitingForPostProcessP* T)
      (vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) "(PostProcess) ")
    )
  )
)

(defun PostProcess ( / enameTxt)
  (print "> PostProcess")
  (if
    (and
      (not (vlax-erased-p (setq enameText (vlr-data *acdbReactor*))))
      (/= (vla-get-textstring (vlax-ename->vla-object enameText)) "Text example")
    )
    (progn
      (print "> PostProcess > Action")
      (vla-put-textstring (vlax-ename->vla-object enameText) "Text example")
    )
  )
  (setq *waitingForPostProcessP* nil)
  (princ)
)

Coder

  • Swamp Rat
  • Posts: 827
Re: Help with reactor
« Reply #10 on: August 14, 2014, 11:26:31 AM »
Hi Roy  :-)

Nothing happen after modifying the text  :-( it does not go back to original text example .

Many thanks

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
Re: Help with reactor
« Reply #11 on: August 14, 2014, 02:23:46 PM »
Here's another way to approach it:

Code - Auto/Visual Lisp: [Select]
  1. (setq write:id "text-reactor")
  2.  
  3. (defun c:write ( / ins )
  4.     (write:removereactors write:id)
  5.     (if (setq ins (getpoint "\nText location: "))
  6.         (vlr-object-reactor
  7.             (list
  8.                 (vla-addtext
  9.                         (if (= 1 (getvar 'cvport))
  10.                             'paperspace
  11.                             'modelspace
  12.                         )
  13.                     )
  14.                     "Text Example"
  15.                     (vlax-3D-point (trans ins 1 0))
  16.                     (getvar 'textsize)
  17.                 )
  18.             )
  19.             write:id
  20.            '((:vlr-modified . write:callback))
  21.         )
  22.     )
  23.     (princ)
  24. )
  25.  
  26. (defun c:unwrite nil
  27.     (write:removereactors write:id)
  28.     (princ)
  29. )
  30.  
  31. (defun write:removereactors ( str )
  32.         (foreach rea (cdr typ)
  33.             (if (= str (vlr-data rea))
  34.                 (vlr-remove rea)
  35.             )
  36.         )
  37.     )
  38. )
  39.  
  40. (defun write:callback ( own rea arg )
  41.     (setq write:data (list own rea))
  42.     (vlr-command-reactor write:id
  43.        '(
  44.             (:vlr-commandended     . write:modify)
  45.             (:vlr-commandcancelled . write:modify)
  46.             (:vlr-commandfailed    . write:modify)
  47.         )
  48.     )
  49.     (princ)
  50. )
  51.  
  52. (defun write:modify ( rea arg )
  53.     (vlr-remove rea)
  54.     (if (and write:data
  55.              (not (wcmatch (strcase (car arg)) "U,UNDO"))
  56.              (vlax-read-enabled-p  (car write:data))
  57.              (/= "Text Example" (vla-get-textstring (car write:data)))
  58.              (vlax-write-enabled-p (car write:data))
  59.         )
  60.         (progn
  61.             (vlr-remove (cadr write:data))
  62.             (vla-put-textstring (car write:data) "Text Example")
  63.             (vlr-add (cadr write:data))
  64.         )
  65.     )
  66.     (setq write:data nil)
  67.     (princ)
  68. )
  69.  
« Last Edit: August 16, 2014, 09:29:21 AM by Lee Mac »

Coder

  • Swamp Rat
  • Posts: 827
Re: Help with reactor
« Reply #12 on: August 15, 2014, 03:45:08 AM »
Thank you so much LEE for your help , it worked like a charm  :-)

Thanks also to ROY for his hard work and lovely willing to help me   :-)

Great people and forum .

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Help with reactor
« Reply #13 on: August 15, 2014, 04:36:56 AM »
FWIW: Here is another attempt using an acdb reactor and a 'PostProcess':
Code: [Select]
(defun c:write (/ pnt enameTxt)
  (vl-load-com)
  (setq pnt (getpoint "\nText location: "))
  (setq enameTxt
    (entmakex
      (list
        '(0 . "TEXT")
        (cons 10 pnt)
        (cons 11 pnt)
        (cons 40 1.0)
        (cons 1 "Text example")
      )
    )
  )
  (setq *acdbReactor*
    (vlr-acdb-reactor
      enameTxt ; Reactor data.
      '((:vlr-objectmodified . CallBackObjectModified))
    )
  )
  (princ)
)

(defun CallBackObjectModified (rea lst)
  (print "> CallBackObjectModified")
  (if
    (and
      (not *postProcessActiveP*)
      (equal (cadr lst) (vlr-data rea))
    )
    (progn
      (print "> CallBackObjectModified > Action: Send command")
      (vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) "(PostProcess) ")
    )
  )
)

(defun PostProcess ( / objectTxt)
  (print "> PostProcess")
  (if
    (and
      (vlax-write-enabled-p (setq objectTxt (vlax-ename->vla-object (vlr-data *acdbReactor*))))
      (vlax-read-enabled-p objectTxt)
    )
    (progn
      (print "> PostProcess > Action")
      (if (/= (vla-get-textstring  objectTxt) "Text example")
        (progn
          (print "> PostProcess > Action > Change text")
          (setq *postProcessActiveP* T)
          (vla-put-textstring objectTxt "Text example")
          (setq *postProcessActiveP* nil)
        )
      )
    )
  )
  (princ)
)

Coder

  • Swamp Rat
  • Posts: 827
Re: Help with reactor
« Reply #14 on: August 15, 2014, 03:51:00 PM »
Roy , it does not work and it behaves like the routine in post No - 6  :-(