I'm currently in the process of building all the DXF app functions.
I've come across a problem. The results from pen should only be output if they are not "by layer". starting here They are all set to "by layer" when drawing, but the results from the DB say something different?? DEBUG: ((-1 . <Entity name: D9>) (0 . "CIRCLE") (330 . <Entity name: D9>) (5 . "D9") (6 . "CONTINUOUS") <-- line type sould be "by Layer" (48 . 0.250000) <-- line width sould be "by Layer" (62 . 7) <-- color sould be "by Layer" (100 . "AcDbEntity") (67 . 0) (100 . "Model") (8 . "0") (100 . "AcDbCircle") (10 74.750000 84.250000 0.000000) (40 . 18.756665) (210 0.000000 0.000000 1.000000)) [RS_Lisp] RS_Lisp::instance requested [entget] LineType: 1 [entget] lineWidth: 25 [entget] color: QColor(ARGB 1, 0, 0, 0) see video: simplescreenrecorder-2025-01-31_13.mp4 |
This is correct behavior.
Please take a look to the method's signature RS_Pen getPen(bool resolve = true) const; By default, pen is resolved - it means, that the method returns resolved pen, i.e final pen that will be used for drawing. In such case, if something is "by layer" - it's resolved to the attribute from the level etc. So, if you need the pen set on the entity itself (where "By Layer"/"By Type" values are fine) - you need to use call like if (e->getId() == en->value()) { RS_Pen pen = e->getPen(false); lclValueVec *entity = new lclValueVec; |
In reply to this post by emanuel
BTW, answering on your question I've took a really quick look on the surrounding code.
Actually, I'm not sure that the general approach you'd like to use is correct. For sure, it's clear that the code LibreCAD/librecad/src/lib/scripting/lisp/Core.cpp attempts to provide a set of API that will be invoked from the scripts. However, I think that the current implementation could be improved, by separation of the API logic itself and language-specific scripting boilerplate code. At the moment, the code there is tightly coupled, as for me. Separation of concerns (api / scripting ) brings several important benefits: 1) API may be be reused, both by core logic and scripting 2) It may be reused by various languages (lisp/python/etc) 3) Scripting subsystem is better isolated from changes in underlying core logic - but relying on API interface instead of internal details. 4) Lot's of internal complexity of the major core is hidden from scripting. 5) Booth classes for scripting and api logic are more compact and maintainable. Basically, the idea behind above is quite straightforward. For example (just as illustration), the method BUILTIN("vl-file-rename") could be implemented as something like this: BUILTIN("vl-file-rename") { CHECK_ARGS_IS(2); ARG(lclString, path); ARG(lclString, newName); book ok = m_scriptingAPI->renameFile(path, newName); return ok ? lcl::trueValue() : lcl::nilValue(); } Where all actual logic of checking file existence and renaming is implemented in method of another class, and m_scriptingAPI is just a reference to such class. The same approach is applicable for other functions. Please consider such decomposition. If you need some additional support with exposing some core logic to scripting or adding some functions that may be used in scripting - please let me know. |
In reply to this post by emanuel
Yes, exactly, that's how I imagine the implementation in the end.
At the moment everything is still in the test development stage, everything is very encapsulated and very redundant (only a rough framework). I wrote the Lisp interpreter before, just for fun. It was a pure command line interpreter. I first tried bit by bit to see if I could integrate it into LibreCAD. (Especially whether it would work with the DCL gui, because the smart Lisp Type classes destroy themselves immediately after use and only appear as constants.) The attempts to port the entire object model to Python using swig make no sense at all for script applications, because it is far too complex and can quickly lead to situations that cause a crash. So I tried to implement what Lisp does in Python in the same way. I will only use this kind of code for LibrePython. The rest will be thrown out of swig. I already use some of the same in Lisp and Python. But it should all be better centralized in a scripting API. My main problem at the moment is that the whole thing is so much work. The object model is still very complex for me and I always try to incorporate as little as possible into the LibreCAD-API source so that the github doesn't break again with the next master update. A scripting API is essential if the whole thing is to work well. Then later on, things like: * shared using LC-API/Plugin/Lisp/Python * Plugin/Lisp/Python reactors/callbacks to functions like in VisualLisp. * Outsourcing and loading the VisualLisp functions in shared plugin libs. * Centralized command alias management... * Centralized menu management... You can't do this alone. I'm grateful for any developer help and especially for tips like the one with the pen. At the moment I have assigned both entity-name (DXF -1), parent-softid name (DXF 330), and the entity-id (DXF 5) group codes to the LC entity id. I don't know how to get the correct entity-name (DXF -1) parent-softid name (DXF 330). |
A lot of coding is hack work that can be templated. Sometimes it can be scripted. I don't mind doing hack work to see new features realised. My preference is to make changes in GitHub using integrated workflow testing. |
In reply to this post by emanuel
oh, I see. And so I could propose you to consider a bit different approach: 1) First, define the interface of that scripting API. For your testing, you may use any dummy implementation (what ever). The idea that you will not bother with LC internals and will be more focused on scripting support part. 2) That interface may be examined, and based on it, it will be clear - what should be changed in LC core (if needed), what is not possible to support at all ( :() or how individual functions should be implemented. Yes, exactly - as I've mentioned earlier - this is a way to nowhere. Plus, it's too complex for the user who will write the script. I think I can support you with implementation of the API if you could define which methods should be there. Yes, the entire plugins system should be reworked. However, plugins support is quite aside of the scripting itselt, I suppose, and proper wrapping of scripts into plugins may be added later on top of the existing code. Well, I suppose Cmd widget will be reworked with better support of command line, and as for aliases - yes, UI for managing them is also planned (yet that's actually is embellishment, as it's just possible to edit .alias file for commands). Oh yes, more flexible menu (and, UI in general) creation is needed and it's also planned. yes, that's was my point - it will be too complex if you'll try to do everything - support scripting part and also implement the underlying logic. That's another reason why api is useful - it will let sharing efforts. No problem, please let me know if you need some assistance. Oh, you've touched quite interesting beast.. Actually, the current way of working with entity's id is quite, well, careless. Each modification of the entity leads to creation of entity's clone - with new ID. I suppose the reason there is related with support of undo - so the entity's state on modification is frozen in the original entity's copy and results of the modifications are stored in entity's clone instance. So for traditional referring entities by IDs - that's currently the issue and thus entity's IDs are actually not persistent (well, they are - but they may be different for the same graphical entity in different versions of the same file). This approach also prevents reliable selecting entities via ID's in the command line. I've planned to review this and check whether it's really necessary to modify id always on cloning - but probably I'll do this earlier to support scripting. Actually, that's another good point why api there is a good thing... |
In reply to this post by emanuel
Well, as for codes - the good source for supported codes (how they are parsed/stored) - it's just the source. Most of the processing is here - libdxfrw.cpp, drw_objects.cpp, drw_entities.cpp. Please also mind that some codes might be not directly exposed by entity. For example, internal DXF code that defines parent may be just parsed and used for adding entity to the necessary container. So the code is disappeared after this and relating exists just as a reference between object instances (until further writing, of course, where the relation will be stored via the code). As for entity-name (DXF -1).. I'm not sure that one is supported by LC at all, at least I cant' see parsing of such code. It might be that this is AutoCAD-specific value. |
The two results are not that important, I can access everything via the ID. I can leave the dummies in there. And I'm putting access to things that are in blocks on hold for now.
My priority at the moment is to get all entities into the ent* DXF APIs, as I'm still missing all the dim, poly, hach, layer functions. At the moment I only have one user ui access for the functions (~scriping API like): https://github.com/emanuel4you/LibreCAD/blob/developer/librecad/src/plugins/intern/qc_actionentsel.h I'll need another one later, but it will be much more complicated: https://help.autodesk.com/view/ACDLT/2024/ENU/?guid=GUID-0F37CC5E-1559-4011-B8CF-A3BA0973B2C3 After that, the most important functions in Lisp would be covered. |
Free forum by Nabble | Edit this page |