top of page
ZackW

FreeCAD Devlog 2 - Copy/Paste Into - Module Development and Commands

Updated: Sep 1, 2022

WIP post!


Module Development

So, while I wait for some feedback from the other freecad developers in the community, I decided to try and actually throw together a module. It isn't clear to me what the difference between workbenches and modules is, after reading all the stuff I've been studying. I'm going to keep calling my thing a Module until someone corrects me though, on account of it not actually being a workbench available to the user. Ideally I could throw together something that wouldn't involve any extra code (like there might for instantiating a workbench vs a module). Where I'm at, while writing this, is I've been trying to get my Clipboard module from before to compile. I've been referencing the Spreadsheet and PartDesign workbenches to piece together mine, but I've gotten stuck at this one error:

It's an annoying one, since the line referenced which is evidentially trying to include a bad dependency works just fine in other workbenches. I'm betting there's something wrong with my cmake configuration files, but haven't figured it out yet. At this point it occurred to me that it would be nice if there was a simpler example workbench, and that maybe one of the third party ones would be worth a look. I should also mention that the 'Complete' workbench doesn't include nearly the same amount of infrastructure that seems to be required.

Anyway, the third party modules (add-ons) all seem to be written in Python. I was expecting that, since I can't imagine the trouble of trying to have dynamically loaded c++ add-ons. So, I think I'm stuck trying to fix that specific error. Aight, so let's get to it. I was still pretty sure it was from my messy cmake configuration I was piecing together like I was Dr. Frankenstein. I saw a couple more patterns in the other modules that I wasn't copying already, specifically the "LIBS" list that was being used elsewhere:

This gets used later with a cmake "target_link_libraries", which makes sense since I believe the error was a linking error. I added my own LIBS set to my cmake file, and then chased my tail for a while before realizing I never re-named it after copying it from the part design file... Anyway, after fixing that oopsie, I get a new error! Hurrah! This project is also turning out to be a trial by fire to learn cmake.


As it turns out, the next errors weren't nearly as difficult to make go away. I say make go away, and not solve, since I still don't have a great grasp on what's going on with all this workbench stuff. Anyway, it looks like I have some sort of basic module!

That's a good sign! We have life! Now, I have no idea what some of the code does but I think I have a basic starting point. If I understand things correctly, I can define my own Commands.cpp file with new commands, and register them when the module is loaded. Understanding how other modules register commands seems much more straightforward.


Workbench / Module Structure

Real quick though, I do want to write down what I used in making all that. It seems that someone (Werner Mayer is in the license) has written some basic workbench files, notably Workbench.h/cpp, and potentially PreCompiled.h/cpp. Before adding the basic skeleton of these files, I was getting a huge python error about a bunch of undefined methods. I think what was happening is I was essentially saying "hey I have a python workbench!" without any kind of C++ backend to it. This makes me doubt if I really need all that framework, but for now I'm going to ignore it and try and get some commands working.


The CMakeLists.txt file seems to require something not much less than this:

Which should make some sense, you tell the compiler what files you want compiled, say what libraries you will be requesting, and add it to a cmake target. In 'src/Mod/CMakeLists.txt', that target is checked for and in 'cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake' it's described and turned on or off. A lot of the complication in other CMakeLists for other modules seems to be related to the QT gui, stuff I'm not using right now and can ignore.


Getting Command

It seems to me that there is an automatic way provided for python scripts to call commands, so the plan is to make a basic debug command in my module and then call it from the interpreter built in to FreeCAD.

For starts, I'm going to define a simple "Hello World" command that just prints something. This command will have to be registered with the core, and include the proper files to do stuff like output to the console. This took me a second to figure out, since at first my ClipboardGui namespace was only defined in my ClipboardGui.cpp file, which I couldn't just include into the Commad.cpp file. I went ahead and just made a ClipboardBase.h file to define the namespace in, but other modules seem to do it a bit differently. Both the spreadsheet and the image module seem to put it in a view provider document. I forget what view providers are exactly, but I don't think they're necessary for what I'm doing. Anyway, it works and I can call my command from the python interpreter! Hurrah!

This has got to be pretty close to the most basic Command.cpp file you can have. I'm not entirely sure what to do with all the tags, but it seems happy with the two I left uncommented around lines 12-18.

At this point I should probably put some retrospective thought and write down a sort of tutorial on module development. I don't know enough to actually do that, unfortunately. In the future I will probably reference this, and the source code, to make new modules if I need to. I would love to strip down everything to exactly what's necessary to get to a command-friendly state, and I have a feeling that all of the nonsense with the python bindings and such isn't strictly necessary. Not sure. This is the current file structure I have:

Replicating Paste

This is quite literally as simple as copying the code over from Gui/CommandDoc.cpp. All you have to do is change the names a bit, include the right header files, and re-register the command under the module. What's immediately annoying, however, is firing the command. I have already studied this a bit but haven't come to any quick fixes yet. Ideally there would be a button or keybinding that I could set that would let me test commands as I make them. For now, I will probably use a python macro. In the future however, some of this might need to appear under the "Customize" menu in FreeCAD.


Adding Paste-Into

This shouldn't be tooo difficult to make a mock-up of. There are examples through FreeCAD's code showing how to check a selection for a certain object type, and how to move objects and set their parent to a different object. I suspect the undo/redo functionality will be a bit larger of a hurdle than this basic stuff.


What is slightly more complicated, is making this robust against different object types and potential changes in the future. I also don't know if any other developer is working on this code with potentially breaking changes. In general the paste engine will need to figure out if we can paste under/into something that's currently selected. If not, we should have the ability to decide whether or not we should paste under something else, or just the document itself.

  • User copies a sketch mapped to a body's origin

  • User selects a different body

  • User activates the paste command

  • Paste engine checks everything that is selected

  • If just one thing is selected

  • Paste engine de-serializes the sketch from the clipboard

  • Paste engine moves the sketch under the selected body




Replicating Copy


Detour Into Git

I have used git a lot in the past, but I have never really gotten a lot of practice with forks, merges, and branches. Basically I've only used it for personal version control of projects. In the process of making my efforts public and available for other people, I have to fork the FreeCAD repository and and push commits to that fork. Of course, I should have done this immediately when deciding to work on FreeCAD, but I didn't.


I started by forking the repository in Github, only grabbing the master branch for now. After doing that, I set my remote origin of my local clone to my own fork, rather than the official repo.

git remote set-url origin git@github.com:zackwhit/FreeCAD.git

I also made an erroneous commit to the master branch, to do undo that I used the command below. Using '--soft' should prevent actually deleting my changes to the files, but as a newby I created a backup of the source folder beforehand anyway.

git reset --soft HEAD^

There was some conflicts in the Gui/CommandDoc.cpp file I had been referencing (and slightly modifying) that would have prevented a fast forward. I probably could have completely discarded those changes, but I chose to stash them since that's something I had never done before.

git stash -- src/Gui/CommandDoc.cpp

After that, I pulled all of the changes and got the master branch up to date. That seemed to work alright, so I made a new branch to put clipboard development changes on.

git branch clipboard

I switched over to that branch and created a commit for my changes:

git checkout clipboard
git commit -m "Test & added new clipboard code"

And then pushed those changes to the remote origin (github), specifically just the changes I made to the clipboard branch. I was also messing around a bit in the master branch and didn't want those changes to get committed.

git push origin clipboard

GitHub provides an excellent overview of the changes that you make in a commit. This is especially convenient when reading other people's commits to learn the codebase.


Other Notes About Git

In learning the FreeCAD environment, going through and reading other people's code and comments is super useful. Git tells the story of each piece of code you're looking at, and the context of the story helps you grasp the purpose and function of the code. To follow the story of different aspects of the code, I found it was useful to find the first pull request or commit in which the code was added. Often times related forum posts are linked in comments on pull requests or github issues, and you get even more exposition that way. From the first commit, following related commits that modify the code over time can be super useful too; you don't want to go making changes that had already been undone by someone else.

19 views0 comments

Recent Posts

See All

Commentaires


bottom of page