Olivier Eckmann Posté(e) le 7 mars 2014 Posté(e) le 7 mars 2014 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-objectClosedDans la fonction appelé par le callback, j'essaie de :1. Lire les Xdatas sur l'objet modifié pour retrouver les handle des objets "enfants" =>OK2. Supprimer les objets "enfants" => OK3. 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 temporaire4. Dessin d'autres objets "enfants"5. Ajout en XData des Handle des objets "enfants" sur l'objet de base => PBDonc 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.MerciOlivier
(gile) Posté(e) le 7 mars 2014 Posté(e) le 7 mars 2014 Salut, As-tu essayé de supprimer l'objet de la liste du réacteur (vlr-owner-remove) avant de le modifier, puis de rajouter à la liste (vl-owner-add) après modification ? Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Olivier Eckmann Posté(e) le 7 mars 2014 Auteur Posté(e) le 7 mars 2014 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
Olivier Eckmann Posté(e) le 10 mars 2014 Auteur Posté(e) le 10 mars 2014 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 fonctionneSi 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:eLockViolationcomme 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
Olivier Eckmann Posté(e) le 10 mars 2014 Auteur Posté(e) le 10 mars 2014 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
(gile) Posté(e) le 10 mars 2014 Posté(e) le 10 mars 2014 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
Olivier Eckmann Posté(e) le 10 mars 2014 Auteur Posté(e) le 10 mars 2014 Merci Gilles, je vais éplucher ça Olivier
(gile) Posté(e) le 10 mars 2014 Posté(e) le 10 mars 2014 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
Olivier Eckmann Posté(e) le 12 mars 2014 Auteur Posté(e) le 12 mars 2014 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
GEGEMATIC Posté(e) le 16 avril 2014 Posté(e) le 16 avril 2014 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/3pour 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.frBlog: http://g-eaux.over-blog.com
Messages recommandés
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 compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant