Aller au contenu

réacteur et XData


Olivier Eckmann

Messages recommandés

Bonjour,

 

J'essaie de jouer avec les réacteurs (non persistent) sur des polylignes.

J'ajoute un réacteur sur mon objet et je réagis sur l’événement ObjectClosed => :vlr-objectClosed

Dans la fonction appelé par le callback, j'essaie de :

1. Lire les Xdatas sur l'objet modifié pour retrouver les handle des objets "enfants" =>OK

2. Supprimer les objets "enfants" => OK

3. Décaler l'objet de base => PB, donc lecture de la géométrie, dessin d'une poly temporaire, décalage de la poly temporaire, suppression de la poly temporaire

4. Dessin d'autres objets "enfants"

5. Ajout en XData des Handle des objets "enfants" sur l'objet de base => PB

Donc a priori, je n'ai pas accès à l'objet en mode modification alors que je réagis sur l'événement ObjectClosed, donc l'objet devrait être fermé par AutoCAD et accessible par ma fonction. A moins que je n'ai pas le droit de modifier l'objet ayant provoqué le réacteur.

En ARX on a un réacteur BeginQuietentSate qui dit qu'AutoCAD ne fait plus rien, mais je n'ai pas trouvé d'équivalent en VLisp.

Est-ce qu'il y a moyen d'ajouter des xdatas sur un objet ayant provoqué un événement?

Dans le tutoriel VLisp, la réaction sur l'objet modifié crée une variable, et c'est le réacteur sur le Command-ended qui provoque le redessin des entités. Est-ce qu'il faut absolument faire comme ça ou bien y a-t-l possibilité de dessiner directement dans le call-back sur l'objet lui-même.

Merci

Olivier

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Effectivement, je vais essayer mais je suis un peu perplexe.

J'ai commencé à mettre en place les réacteurs comme dans le tutoriel VLisp.

Ca a l'air de fonctionner, mais c'est pas simple à gérer (et à débugger) avec les Undo aussi.

 

Je vais continuer à chercher.

 

Merci

 

Olivier

Lien vers le commentaire
Partager sur d’autres sites

Bon je progresse, mes réacteurs (sur Command-ended) fonctionnent bien sur la modification d'un objet, sa copie, son effacement...

 

Par contre j'ai un souci à l'ouverture du dessin, le but étant que le chargement de mon VLX restaure les réacteurs (non persistants).

Pour cela, je stocke en XData 2 types d'infos:

- Application enregistrée : "ReacteurPerso" valeur 1000 "ReacteurPersoType1"

- App enreg : "ReacteurPersoType1" valeur ... (toutes les infos nécessaire à mon réacteur : handle "enfant" + paramètres)

 

mon appli lit la base DWG en filtrant sur l'appli ReacteurPerso : (ssget "x" (list (cons -3 (list (list "ReacteurPerso")))))

et s'il y en a, je reconstruis les réacteurs sur les objets "parents"

 

Si j'ouvre mon dessin, puis que je lance ma fonction pas de souci tout fonctionne

Si j'inclue cette fonction dans mon VLX et que je fais charger mon VLX au démarrage, alors j'ai un plantage

scandr.cpp@2313:eLockViolation

comme si le VLX se chargeait avant que le dessin ne soit dispo pour en faire quoique ce soit.

 

J'ai essayé de voir si je pouvais mettre en place un réacteur sur l'évènement :vlr-dwgFileOpened mais ça ne fonctionne pas (en tout cas je ne reçois pas la notification dans le dessin qui vient de s'ouvrir) d'ailleurs quel dessin est censé recevoir la notification, est-ce lui même, ou bien le dessin courant précédent, ou bien l'éditeur?

 

Si quelqu'un (Gile) a une piste de recherche je suis preneur?

 

Merci

 

Olivier

Lien vers le commentaire
Partager sur d’autres sites

Ca y est c'est réglé.

En fait en balayant la liste des objets ayant un réacteur à restaurer, je créais le réacteur sur le 1er, puis j'ajoutais un par un les objets à mon réacteur (vlr-owner-add), ce qui déclenchait le réacteur sur les objets déjà présents dans le réacteur => boucle infinie + plantage.

 

En créant le réacteur avec la liste de tous les objets en une fois, ça ne plante plus.

 

Ceci dit, si quelqu'un a la réponse sur le réacteur :vlr-dwgFileOpened pour savoir quel dessin est notifié, je suis preneur de l'info.

 

Olivier

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Je fais quelque chose de similaire avec TotalArea et TotalPerim (recréation des réacteurs à l'ouverture du dessin). Il y en a une version compilée (VLX) qui est incluse dans une application plus importante (CADnorm TOOLS), cette application est chargée à l'ouverture de chaque dessin (via un ficher MNL) et fonctionne correctement.

Tu peux peut-être t'inspirer du code de TotalArea, le code concernant la recrétion des réacteurs est à la fin du fichier TotalArea.lsp.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Je te donnes quelques explications parce que je sais ce n'est pas facile de lire du code écrit par d'autres (surtout quand il n'y a pas de commentaires).

 

Le contexte :

Une (ou plusieurs) polyligne(s) sont liées à un bloc (TotalArea) par un (ou des) reacteur(s) objet (vlr-object-reactor). Deux attributs dans le bloc (AREA et NUMOBJ) affichent respectivement l'aire totale de la (ou des) polyligne(s) et le nombre de polylignes liées au bloc.

Le (ou les) handle(s) de la (ou des) polylignes sont stockées dans un dictionnaire LISP (ldata) du bloc (ça aurait très bien pu être des xdata ou un xrecord dans le dictionnaire d'extension).

 

Le code pour reconstruire les réacteurs à l'ouverture du dessin:

((lambda (/ ss obj)
  (foreach r (cdr (assoc :VLR-Object-Reactor (vlr-reactors)))
    (if (member '(:VLR-erased . GC:AREAOBJECTERASED)
	 (vlr-reactions r)
 )
      (vlr-remove r)
    )
  )
  (if (ssget "_X" '((0 . "INSERT") (2 . "TotalArea,`*U*")))
    (progn
      (vlax-for blk (setq ss (vla-get-ActiveSelectionSet *acdoc*))
 (if (and
       (vlax-property-available-p blk 'EffectiveName)
       (= (strcase (vla-get-EffectiveName blk)) "TOTALAREA")
     )
   (progn
     (foreach hand (vlax-ldata-get blk "TotalArea")
       (if (setq obj (gc:HandleToObject hand))
	 (vlr-object-reactor
	   (list obj)
	   (vla-get-Handle blk)
	   '((:vlr-erased . GC:AREAOBJECTERASED)
	     (:vlr-unerased . GC:AREAOBJECTUNERASED)
	     (:vlr-objectClosed . GC:AREAOBJECTMODIFIED)
	    )
	 )
       )
     )
     (gc:TotalAreaUpd
       blk
       (mapcar 'gc:HandleToObject
	       (vlax-ldata-get blk "TotalArea")
       )
     )
   )
 )
      )
      (vla-delete ss)
    )
  )
)
)

 

 

La première expression (foreach ...) supprime les réacteurs persistants. Il ne devrait pas y en avoir mais on n'est jamais trop prudent.

 

Ensuite, sur une sélection de tous les blocs "TotalArea", pour chaque bloc, on récupère les handles contenus dans le dictionnaire du bloc et pour chaque polyligne (on teste si elle existe toujours avec gc:HandleToObject) on recrée le réacteur, puis on met à jour les attributs du bloc (gc:TotalAreaUpd).

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Merci pour le code d'exemple, c'est très clair.

En fait dans ton exemple, le réacteur sur une polyligne met à jour un autre objet et son handle ne change pas, ce qui te permet de créer un réacteur par objet et de tout faire dans le call-back puisque l'objet ayant réagit n'est pas modifié, juste interrogé.

 

Dans mon cas, le réacteur sur l'objet reconstruit des enfants à partir de l'objet ayant réagit. Pour ne pas avoir à toucher l'objet dans le call-back, il faudrait que les handle des enfants créés soit mis à jour dans un xrecord et que le parent pointe toujours sur le même xrecord. Par contre le problème c'est que si le copie/wbloc mes objets, le xrecord ne le sera pas et je vais perdre mon associativité.

Ca m'oblige donc a réagir dans le command-ended et donc de connaître le réacteur => construction d'un seul réacteur nommé et ajout de tous les objets dedans.

 

Ca fonctionne mais c'est quand même un peu compliqué; je vas voir si je ne peux pas avoir un enfant principal qui connait les autres objets et l'objet de base ne connaîtra que cet enfant dont je ne ferais que mettre à jour la géométrie (sans changer son Handle).

 

J'avais une autre question sur ton code. Tu gères l’événement vlr-unerased. A part dans le cas d'un UNDO qui devrait tout rétablir, dans quel cas cet événement se déclenche et qu'est-ce que tu fais dans le call-back? Y a-t-il quelque chose de particulier à rétablir?

Dans mon code je ne l'ai pas géré et ça semble fonctionner correctement dans la commande Annuler.

 

Olivier

Lien vers le commentaire
Partager sur d’autres sites

  • 1 mois après...

Salut Olivier,

je ne suis pas rentré dans le détail de ton problème de réacteurs,

les seuls que j'utilise sont persistants.

Par contre, pour le comportement de la persistance des liens, mes articles peuvent t' intéresser :

Liens entre les entités Autocad avec Visual Lisp 1/3

pour le 1er des 3.

ce n'est pas encore complet, j'ai encore des choses à dire sur les objectid, mais le temps me manque ...

Gérald

----------------------------------------------------------------------

Site: https://www.g-eaux.fr

Blog: http://g-eaux.over-blog.com

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité