;; ============================================================ ;; SSG_LIB - Befehlsdefinitionen fuer Menue SSG_LIB ;; Enthaelt implementierte Befehle (BTMT Be-/Entladung, Sensoren, ;; Konfiguration, SSG_BLOCKEDIT) und Dummy-Befehle, die nur eine ;; Meldung ausgeben und spaeter durch echte Funktionalitaet ;; ersetzt werden. ;; ============================================================ ;; ssg-ils-block-ebene (ssg_core.lsp) arbeitet ueber die VLA-Blocktabelle (vl-load-com) ;; --- ILS / Zusatzmodul: BTMT Be-/Entladestation einfuegen --- ;; ROH-Blocknamen (ohne Dimensionssuffix) der beiden Stationen. Das Suffix ;; _2D/_3D haengt zentral ssg-ils-blockname-dim an; die BTMT-Entladung liegt ;; als SC_Entladung_.dwg in data/ils. (if (null *ils-btmt-beladung-block*) (setq *ils-btmt-beladung-block* "BTMT-Beladung")) (if (null *ils-btmt-entladung-block*) (setq *ils-btmt-entladung-block* "SC_Entladung")) ;; Layer einer frisch eingefuegten Blockreferenz setzen: bevorzugt aus dem ;; LAYER-Attribut des Blocks (gleiche Konvention wie omni:insert-dxf in ;; OmniModulInsert.lsp und tefl-insert-element in TEFInsert.lsp), sonst aus der ;; "eigenen" Ebene der Blockdefinition (ssg-ils-block-ebene). Liefert der Block ;; beides nicht, bleibt die Referenz auf dem aktuellen Layer. ;; Rueckgabe: gesetzter Layername oder nil. (defun ils-block-layer-setzen (ent realname attribs / lay) (setq lay (cdr (assoc "LAYER" attribs))) (if (or (null lay) (= lay "")) (setq lay (ssg-ils-block-ebene realname)) ) (if (and lay (/= lay "")) (progn (ssg-make-layer lay 7 nil) (entmod (subst (cons 8 lay) (assoc 8 (entget ent)) (entget ent))) (entupd ent) lay ) ) ) ;; Fuegt eine ILS-Station (BTMT-Beladung/SC_Entladung) wiederholt ein, bis der ;; Benutzer mit ENTER oder ESC abbricht. Je Einfuegung wird der Einfuegepunkt ;; abgefragt, die Drehung bestimmt der Benutzer interaktiv am Cursor (pause). ;; ;; Die Blockdefinition kommt ueber den zentralen Loader in der AKTUELLEN ;; Dimension (ssg-ils-block-laden: *ssg-ils-dim* -> DXFM_DIM, Default 3D); ;; eingefuegt wird danach der zurueckgegebene effektive, dim-suffigierte ;; Blockname. Fehlt die Datei der gewuenschten Dimension, greift der ;; 3D-Fallback aus ssg-ils-block-datei-dim (mit Warnung) - sobald also z.B. ;; BTMT-Beladung_2D.dwg in data/ils liegt, wird sie im 2D-Modus automatisch ;; verwendet, ohne Codeaenderung. Anders als ils-insert-sensor wird hier NICHT ;; per Dateipfad eingefuegt: das laedt die DWG bei jeder Einfuegung erneut von ;; der Platte, was bei den grossen 3D-Stationen (BTMT-Beladung_3D ~5 MB) teuer ;; ist - der Loader liest sie dagegen nur einmal pro Zeichnung ;; (Redefine-Sperre, siehe ssg_core.lsp). (defun ils-insert-station (rohname / eff res pt vorher ent attribs n) (ssg-start (strcat "ILS " rohname) '(("OSMODE") ("ATTREQ") ("ATTDIA"))) (setq eff (ssg-ils-block-laden rohname)) (if (null eff) (princ (ssg-textf "ils-station-fehler-blockdatei" (list (ssg-ils-blockname rohname)))) (progn (setvar "ATTREQ" 0) (setvar "ATTDIA" 0) (setq n 0) ;; Punkt abfragen; ENTER liefert nil, ESC einen abgefangenen Fehler - ;; beides beendet die Schleife sauber (ssg-end stellt danach die ;; Systemvariablen wieder her). (while (progn (setq res (vl-catch-all-apply 'getpoint (list (ssg-textf "ils-station-prompt-punkt" (list eff))))) (and (not (vl-catch-all-error-p res)) res) ) (setq pt res) (setq vorher (entlast)) (command "_.INSERT" eff pt "" "" pause) ;; Laufende Einfuegung sicher beenden (z.B. ESC waehrend der Drehung). (if (> (getvar "CMDACTIVE") 0) (command)) (if (> (getvar "CMDACTIVE") 0) (command)) (setq ent (entlast)) ;; Nur weiterarbeiten, wenn wirklich eine neue Blockreferenz entstanden ;; ist (abgebrochene Einfuegung liefert weiterhin 'vorher'). (if (and ent (not (eq ent vorher)) (= (cdr (assoc 0 (entget ent))) "INSERT")) (progn (setq attribs (ssg-attrib-read ent)) (ils-block-layer-setzen ent eff attribs) ;; ID nur vergeben, wenn der Block ueberhaupt ein ID-Attribut fuehrt: ;; ohne ID-ATTDEF verwirft ssg-attrib-set-on die Zuweisung still und ;; die Meldung aus ssg-id-generate waere irrefuehrend (siehe ;; ssg-id-set-and-verify in ssg_id.lsp). (if (and (assoc "ID" attribs) (car (atoms-family 1 '("SSG-ID-GENERATE")))) (ssg-id-generate ent) ) (setq n (1+ n)) ) ) ) (princ (ssg-textf "ils-station-fertig" (list (itoa n) eff))) ) ) (ssg-end) (princ) ) (defun c:ILS_BTMT_Beladung () (ils-insert-station *ils-btmt-beladung-block*) ) (defun c:ILS_BTMT_Entladung () (ils-insert-station *ils-btmt-entladung-block*) ) ;; --- ILS / Zusatzmodul: Sensoren (Scanner / Separator) einfuegen --- ;; Ermittelt den Pfad zu einer Sensor-Blockdatei. Folgt der 2D/3D-Umschaltung ;; (DXFM_DIM) mit automatischem 3D-Fallback - Scanner/Separator sind in 2D und ;; 3D identisch, laden also in beiden Modi korrekt. (defun ils-sensor-pfad (fname) (ssg-ils-block-datei fname) ) ;; Fuegt einen Sensor-Block wiederholt ein, bis der Benutzer mit ;; ENTER oder ESC abbricht. Rotation je Einfuegung interaktiv. (defun ils-insert-sensor (fname / pfad pt oldattreq n res) (setq pfad (ils-sensor-pfad fname)) (if (null pfad) (princ (strcat "\n>>> FEHLER: Blockdatei '" fname ".dwg' nicht gefunden." " (in data/ils/ bzw. data/ils/3D pruefen)")) (progn (setq oldattreq (getvar "ATTREQ")) (setvar "ATTREQ" 0) (setq n 0) ;; Punkt abfragen; ENTER liefert nil, ESC einen abgefangenen Fehler - ;; beides beendet die Schleife sauber (ATTREQ wird wiederhergestellt). (while (progn (setq res (vl-catch-all-apply 'getpoint (list (strcat "\nEinfuegepunkt fuer " fname " [ENTER=Ende]: ")))) (and (not (vl-catch-all-error-p res)) res) ) (setq pt res) (command "_.INSERT" pfad pt "" "" pause) ;; Sofort beim Einfuegen eine eindeutige ID vergeben - wie bei allen ;; anderen Bau-Routinen (Kreisel/GF/VF/Omniflo, siehe ssg-id-generate- ;; Aufrufe dort). Separator/Scanner waren bisher die einzige Ausnahme ;; und bekamen ihre ID erst nachtraeglich, gesammelt fuer alle Bloecke ;; auf einmal, durch ssg-id-check-all vor dem naechsten Export - ;; das ist der Fall, den ssg-id-check-all als Sicherheitsnetz ;; eigentlich nur fuer Kopier-/Array-/Spiegel-Faelle abfangen soll. (if (atoms-family 1 '("ssg-id-generate")) (ssg-id-generate (entlast))) (setq n (1+ n)) ) (setvar "ATTREQ" oldattreq) (princ (strcat "\n>>> " (itoa n) " x " fname " eingefuegt.")) ) ) (princ) ) (defun c:ILS_SCANNER_INSERT () (ils-insert-sensor "Scanner") ) (defun c:ILS_SEPARATOR_INSERT () (ils-insert-sensor "Separator_SP") ) ;; --- ILS / Foerderer --- (defun c:ILS_TEF_Strecke () (princ "\n[DUMMY] ILS_TEF_Strecke aufgerufen") (princ) ) ;; FOERDERANLAGE ist bereits in VarioFoerderer.lsp definiert ;; Kurven angetrieben Aussen (defun c:ILS_K90LA () (princ "\n[DUMMY] 90 Kurve links angetrieben Aussen") (princ) ) (defun c:ILS_K90RA () (princ "\n[DUMMY] 90 Kurve rechts angetrieben Aussen") (princ) ) (defun c:ILS_K60LA () (princ "\n[DUMMY] 60 Kurve links angetrieben Aussen") (princ) ) (defun c:ILS_K60RA () (princ "\n[DUMMY] 60 Kurve rechts angetrieben Aussen") (princ) ) (defun c:ILS_K30LA () (princ "\n[DUMMY] 30 Kurve links angetrieben Aussen") (princ) ) (defun c:ILS_K30RA () (princ "\n[DUMMY] 30 Kurve rechts angetrieben Aussen") (princ) ) ;; Kurven angetrieben Innen (defun c:ILS_K90LI () (princ "\n[DUMMY] 90 Kurve links angetrieben Innen") (princ) ) (defun c:ILS_K90RI () (princ "\n[DUMMY] 90 Kurve rechts angetrieben Innen") (princ) ) (defun c:ILS_K60LI () (princ "\n[DUMMY] 60 Kurve links angetrieben Innen") (princ) ) (defun c:ILS_K60RI () (princ "\n[DUMMY] 60 Kurve rechts angetrieben Innen") (princ) ) (defun c:ILS_K30LI () (princ "\n[DUMMY] 30 Kurve links angetrieben Innen") (princ) ) (defun c:ILS_K30RI () (princ "\n[DUMMY] 30 Kurve rechts angetrieben Innen") (princ) ) ;; --- ILS / Gefaellestrecke --- (defun c:ILS_Gefaellestrecke () (princ "\n[DUMMY] ILS_Gefaellestrecke aufgerufen") (princ) ) (defun c:ILS_GK90L () (princ "\n[DUMMY] 90 Kurve links Gefaellestrecke") (princ) ) (defun c:ILS_GK90R () (princ "\n[DUMMY] 90 Kurve rechts Gefaellestrecke") (princ) ) (defun c:ILS_GK60L () (princ "\n[DUMMY] 60 Kurve links Gefaellestrecke") (princ) ) (defun c:ILS_GK60R () (princ "\n[DUMMY] 60 Kurve rechts Gefaellestrecke") (princ) ) (defun c:ILS_GK30L () (princ "\n[DUMMY] 30 Kurve links Gefaellestrecke") (princ) ) (defun c:ILS_GK30R () (princ "\n[DUMMY] 30 Kurve rechts Gefaellestrecke") (princ) ) ;; ============================================================ ;; SSG_DIM_SWITCH - Umschalten zwischen 2D und 3D Bloecken ;; Setzt DXFM_DIM, DXFM_BLOCKS und DXFM_OMNIFLO neu ;; ============================================================ (defun c:SSG_DIM_SWITCH ( / dim-global dim-neu basis) ;; Globalen Modus lesen: NUR DXFM_DIM + Fallback "3D". ;; Bewusst KEIN *ssg-ils-dim* - das ist ein transienter GUI-Override ;; pro Einfuegevorgang und soll den globalen Schalter nicht beeinflussen. (setq dim-global (cond ((= (type (getenv "DXFM_DIM")) 'STR) (strcase (getenv "DXFM_DIM"))) (t "3D"))) (setq dim-neu (if (equal dim-global "3D") "2D" "3D")) (setq basis (getenv "DXFMAKRO")) (setenv "DXFM_DIM" dim-neu) ;; ILS-Bloecke liegen flach unter data\ils (Dimension im Dateinamen) - kein ;; -Unterordner mehr. Omniflo behaelt die alte Struktur. (setenv "DXFM_BLOCKS" (strcat basis "\\data\\ils")) (setenv "DXFM_OMNIFLO" (strcat basis "\\data\\omniflo\\" dim-neu)) (princ (ssg-textf "dim-switch-modus" (list dim-neu))) (princ (ssg-textf "dim-switch-blocks" (list (getenv "DXFM_BLOCKS")))) (princ (ssg-textf "dim-switch-omniflo" (list (getenv "DXFM_OMNIFLO")))) (princ) ) ;; ============================================================ ;; SSG_DIM_ALL_2D / SSG_DIM_ALL_3D - alle GF/VF-Bloecke der Zeichnung ;; auf einmal in 2D bzw. 3D umwandeln (loeschen + neu aufbauen). ;; ============================================================ (defun ssg-dim-alle-umwandeln (ziel-dim / ss i enames ent bname akt n-gf n-vf n-skip) ;; Feature-Module sicherstellen (Konverter-Funktionen + Bau-Logik) (if (car (atoms-family 1 '("SSG-ENSURE"))) (progn (ssg-ensure "Gefaellestrecke") (ssg-ensure "VarioFoerderer"))) (setq enames '() n-gf 0 n-vf 0 n-skip 0) (ssg-start "SSG_DIM_BATCH" '(("OSMODE") ("ATTREQ") ("ATTDIA"))) (setvar "OSMODE" 0) ;; Erst alle enames sammeln (entdel veraendert die Zeichnung waehrend der Iteration) (setq ss (ssget "X" '((0 . "INSERT") (2 . "GF_*,VF_*")))) (if ss (progn (setq i 0) (while (< i (sslength ss)) (setq enames (cons (ssname ss i) enames)) (setq i (1+ i))) (foreach ent enames (if (entget ent) ; noch vorhanden? (progn (setq bname (cdr (assoc 2 (entget ent)))) (setq akt (cond ((ssg-dim-xdata-lesen ent)) ("3D"))) (cond ((equal akt ziel-dim) (setq n-skip (1+ n-skip))) ; schon Zieldim ((wcmatch bname "GF_*") (if (gf-konvertiere-ent ent ziel-dim) (setq n-gf (1+ n-gf)))) ((wcmatch bname "VF_*") (if (vf-konvertiere-ent ent ziel-dim) (setq n-vf (1+ n-vf)))))))) ) ) (ssg-end) (princ (ssg-textf "dim-batch-fertig" (list ziel-dim (itoa n-gf) (itoa n-vf) (itoa n-skip)))) (princ) ) (defun c:SSG_DIM_ALL_2D ( / ) (ssg-dim-alle-umwandeln "2D")) (defun c:SSG_DIM_ALL_3D ( / ) (ssg-dim-alle-umwandeln "3D")) ;; ============================================================ ;; SSG_SPRACHE - Sprache umschalten (Deutsch/Englisch) ;; Setzt *ssg-lang* live und persistiert ueber DXFM_LANG ;; ============================================================ (defun ssg-sprache-init ( / idx) (start_list "sprache") (add_list "Deutsch") (add_list "Englisch") (end_list) (setq idx (if (= *ssg-lang* "en_GB") "1" "0")) (set_tile "sprache" idx) ) (defun ssg-sprache-accept ( / idx neu) (setq idx (get_tile "sprache")) (setq neu (if (= idx "1") "en_GB" "de_DE")) (setq *ssg-lang* neu) (setenv "DXFM_LANG" neu) ) (defun c:SSG_SPRACHE () (ssg-dialog-run (strcat (getenv "DXFM_DCL") "/sprache.dcl") "sprache" 'ssg-sprache-init 'ssg-sprache-accept ) (princ (ssg-textf "sprache-gewechselt" (list *ssg-lang*))) (princ) ) ;; ============================================================ ;; SSG_BLOCKEDIT - Kontextmenue-Dispatcher ;; Erkennt den selektierten Blocktyp und ruft den passenden ;; Bearbeitungsbefehl auf (Rechtsklick-Kontextmenue). ;; ============================================================ (defun c:SSG_BLOCKEDIT ( / ss ent ed bname attribs teileart) ;; Block ermitteln: zuerst Implied Selection, dann Picking (setq ss (ssget "I")) (if (or (null ss) (/= (sslength ss) 1)) (progn (princ (ssg-text "cmd-block-auswaehlen")) (setq ss (ssget ":S" '((0 . "INSERT")))) ) ) (if (null ss) (progn (princ (ssg-text "cmd-kein-block-ausgewaehlt")) (princ) (exit) ) ) (setq ent (ssname ss 0)) (setq ed (entget ent)) (if (/= (cdr (assoc 0 ed)) "INSERT") (progn (princ (ssg-text "cmd-kein-block-ausgewaehlt")) (princ) (exit) ) ) (setq bname (cdr (assoc 2 ed))) (cond ;; Kreisel-Bloecke -> KreiselEdit ((wcmatch bname "KREISEL_*") (princ (ssg-textf "cmd-kreisel-bearbeiten" (list bname))) (c:KreiselEdit) ) ;; Eckrad-Bloecke -> BEDIT (kein eigener Edit-Dialog in LISP) ((wcmatch bname "ECKRAD_*") (princ (ssg-textf "cmd-eckrad-bearbeiten" (list bname))) (command "_.BEDIT" bname) ) ;; Gefaellestrecke-Bloecke (GF_n) -> GEFAELLESTRECKE_EDIT (DCL-Dialog) ((wcmatch bname "GF_*") (princ (ssg-textf "cmd-gefaelle-bearbeiten" (list bname))) (c:GEFAELLESTRECKE_EDIT) ) ;; VarioFoerderer-Bloecke (VF_n) -> VARIOFOERDERER_EDIT (DCL-Dialog); ;; weist Bloecke ohne SSG_VF_EDIT-XDATA (Etage/Linienzug/Altbestand) ;; intern selbst ab, siehe c:VARIOFOERDERER_EDIT in vf_standard.lsp. ((wcmatch bname "VF_*") (princ (ssg-textf "cmd-variofoerderer-bearbeiten" (list bname))) (c:VARIOFOERDERER_EDIT) ) ;; TRO-Marker (TRO_SYM_) -> TRO_EDIT (DCL-Dialog) ;; Die Marker kommen aus sps_skel (lib/tro_annotate.py) und tragen die ;; Attribute ID und TYPE. Modul bei Bedarf nachladen, damit der Doppelklick ;; auch ohne vorherigen Menueaufruf funktioniert. ((wcmatch bname "TRO_*") (princ (ssg-textf "cmd-tro-bearbeiten" (list bname))) (if (and (null *ssg-Tro_Edit-loaded*) (atoms-family 1 '("SSG-ENSURE"))) (ssg-ensure "Tro_Edit") ) (if (atoms-family 1 '("C:TRO_EDIT")) (c:TRO_EDIT) (progn (princ (ssg-textf "tro-edit-modul-fehlt" (list "Tro_Edit.lsp"))) (command "_.EATTEDIT") ) ) ) ;; Omniflo-Bloecke -> OMNI_EDIT ;; Erkennung: TEILEART-Attribut vorhanden, AP110-Blockname oder rein numerisch ((progn (setq attribs (ssg-attrib-read ent)) (setq teileart (cdr (assoc "TEILEART" attribs))) (or teileart (wcmatch (strcase bname) "AP110*,AP_110*,APG110*") (wcmatch bname "#*") ) ) (princ (ssg-textf "cmd-omniflo-bearbeiten" (list bname))) (c:OMNI_EDIT) ) ;; Unbekannter Blocktyp -> natives EATTEDIT (Attribut-Editor) (t (princ (ssg-textf "cmd-attribute-bearbeiten" (list bname))) (command "_.EATTEDIT") ) ) (princ) ) ;; ============================================================ ;; C:EATTEDIT - Abfangen des eingebauten Doppelklick-Befehls ;; UNDEFINE zwingt BricsCAD, auch interne Aufrufe ueber LISP ;; zu leiten. Fallback auf _.EATTEDIT (Dot-Prefix = nativ, ;; kein Loop) fuer unbekannte Bloecke. ;; ============================================================ (defun c:EATTEDIT () (c:SSG_BLOCKEDIT) ) (if (not *ssg-eattedit-undefined*) (progn (command "_.UNDEFINE" "EATTEDIT") (setq *ssg-eattedit-undefined* t) ) ) (princ "\nSSG_LIB_Commands.lsp geladen - Dummy-Befehle registriert.") (princ)