[Solved] How to select a point on Sketcher's screen for use in a macro?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: How to select a point on Sketcher's screen for use in a macro?

Post by openBrain »

ifohancroft wrote: Sat Sep 25, 2021 3:21 am 1. The ActiveSketch object doesn't get deleted when the Sketch does. What way would you recommend to check for the presence of an active sketch before drawing geometry or adding constraints? If you try to add geometry to a deleted sketch, by using ActiveSketch, there are no errors, just nothing happens, but I'd still like to have a proper check in place.
If your point is about determining if a sketch is currently in edition mode, see here : https://forum.freecadweb.org/viewtopic. ... 57#p418157
2. My custom cursor is too big. Is it the SVG file I have used or do I have to specify the scale or something? I couldn't actually find where FreeCAD holds its UI icons, so I downloaded the SVG from the wiki, then modified it a bit.
You can give the size when generating the pixmap : https://doc.qt.io/qt-5/qpixmap.html#QPixmap
3. I am trying to imitate Sketcher's own tools with this macro, so I've made it that once you start it, you can keep clicking in the document and it will keep "drawing", unless you hit the right mouse button. Hitting the right mouse button shows the context menu on screen. Is there a way to prevent the context screen from showing when hitting the right mouse button while the macro is working?

Also, I just discovered that hitting the right mouse button doesn't actually stop the macro. Am I removing the event callback the wrong way?
I think the problem here is that the right click event is consumed by FreeCAD and not passed to your macro. You can test it with the dialog example I posted above. This a problem and you have to choose a combination that you will receive to remove the callback
3.1. Sketcher's native tools also stop working when you select another geometry tool or constraint - Can I catch the selection of another tool, so I can stop my macro when that happens?
I don't think you can really do this. The solution would be that your macro adds a custom command to the Sketcher toolbar, rather than just executing the script.
4. I doubt that's possible, but if I add an icon for my macro to Sketcher's toolbar (by going to Tools > Customize > Macros, selecting a pixmap, etc, then going to the Sketcher's toolbar, adding a new one, adding the icon to it, etc), is it possible to make the icon be grayed out and unclickable when I am not editing a Sketch? (I.e. the way the icons for Sketch's own tools work)?
Same as above. Would solve the problem
P.S. Any tips for improving my macro further?
Looks quite correct ATM. :)
User avatar
ifohancroft
Posts: 205
Joined: Fri May 31, 2019 11:25 pm
Location: Sofia, Bulgaria
Contact:

Re: How to select a point on Sketcher's screen for use in a macro?

Post by ifohancroft »

openBrain wrote: Mon Sep 27, 2021 8:23 am
ifohancroft wrote: Sat Sep 25, 2021 3:21 am 1. The ActiveSketch object doesn't get deleted when the Sketch does. What way would you recommend to check for the presence of an active sketch before drawing geometry or adding constraints? If you try to add geometry to a deleted sketch, by using ActiveSketch, there are no errors, just nothing happens, but I'd still like to have a proper check in place.
If your point is about determining if a sketch is currently in edition mode, see here : https://forum.freecadweb.org/viewtopic. ... 57#p418157
No. I am trying to figure out if a sketch still exists so I don't try to execute my code if the sketch got deleted. However, I can't use ActiveSketch to check for that, because apparently it still holds the sketch object, even after the sketch is deleted.


2. My custom cursor is too big. Is it the SVG file I have used or do I have to specify the scale or something? I couldn't actually find where FreeCAD holds its UI icons, so I downloaded the SVG from the wiki, then modified it a bit.
You can give the size when generating the pixmap : https://doc.qt.io/qt-5/qpixmap.html#QPixmap
Thank you! I'd look into that.
I forgot to add this, just in-case it isn't the scale's problem: It's not just that the cursor is bigger than expected, the cursor's "point" doesn't fall on the cross in the image, but somewhere between the cross and the the other image in the cursor. So basically the custom cursor gets centered around the actual cursor.


3. I am trying to imitate Sketcher's own tools with this macro, so I've made it that once you start it, you can keep clicking in the document and it will keep "drawing", unless you hit the right mouse button. Hitting the right mouse button shows the context menu on screen. Is there a way to prevent the context screen from showing when hitting the right mouse button while the macro is working?

Also, I just discovered that hitting the right mouse button doesn't actually stop the macro. Am I removing the event callback the wrong way?
I think the problem here is that the right click event is consumed by FreeCAD and not passed to your macro. You can test it with the dialog example I posted above. This a problem and you have to choose a combination that you will receive to remove the callback
That's the problem, that my macro received the right click event, as on right click I try to stop the macro and reset the cursor image. The resetting cursor image works. However, stopping the macro (self.view.removeEventCallback("SoMouseButtonEvent", self.viewObserver)) doesn't and I don't get an error.


3.1. Sketcher's native tools also stop working when you select another geometry tool or constraint - Can I catch the selection of another tool, so I can stop my macro when that happens?
I don't think you can really do this. The solution would be that your macro adds a custom command to the Sketcher toolbar, rather than just executing the script.
In such a case I might strip down the macro to just getting the coordinates and drawing around them. I will be turning most of my macros in a workbench soon anyway.

Do you happen to know if input and tools are handled differently when writing a workbench (in Python)? Like would I have access to more events there? Such as when another tool gets selected or have access to the mouse coordinates and click events without needing to add a ViewObserver as a callback to the view? etc.. So I can make the tools appear more native?
4. I doubt that's possible, but if I add an icon for my macro to Sketcher's toolbar (by going to Tools > Customize > Macros, selecting a pixmap, etc, then going to the Sketcher's toolbar, adding a new one, adding the icon to it, etc), is it possible to make the icon be grayed out and unclickable when I am not editing a Sketch? (I.e. the way the icons for Sketch's own tools work)?
Same as above. Would solve the problem
Sorry, what would solve the problem? I mean when you said same as the above, I thought you meant that it's not possible?


P.S. Any tips for improving my macro further?
Looks quite correct ATM. :)
Thank you!
I like making, breaking and modding stuff, using a soldering iron, code or both. https://ifohancroft.com
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: How to select a point on Sketcher's screen for use in a macro?

Post by openBrain »

ifohancroft wrote: Mon Sep 27, 2021 11:22 am No. I am trying to figure out if a sketch still exists so I don't try to execute my code if the sketch got deleted. However, I can't use ActiveSketch to check for that, because apparently it still holds the sketch object, even after the sketch is deleted.
Would need to know which information you have as a reference.
You can test with something like :

Code: Select all

hasattr(App.ActiveDocument, "SKETCHNAME")
3. I am trying to imitate Sketcher's own tools with this macro, so I've made it that once you start it, you can keep clicking in the document and it will keep "drawing", unless you hit the right mouse button. Hitting the right mouse button shows the context menu on screen. Is there a way to prevent the context screen from showing when hitting the right mouse button while the macro is working?
AFAIK you can't prevent context menu to appear
Also, I just discovered that hitting the right mouse button doesn't actually stop the macro. Am I removing the event callback the wrong way?
Yes, your line should be

Code: Select all

self.view.removeEventCallback("SoMouseButtonEvent", self.view_callback)
Do you happen to know if input and tools are handled differently when writing a workbench (in Python)? Like would I have access to more events there? Such as when another tool gets selected or have access to the mouse coordinates and click events without needing to add a ViewObserver as a callback to the view? etc.. So I can make the tools appear more native?
In a certain way, you have access to more events. In a workbench, you will use "Command" type to create the toolbar features. There will so be a mechanism that will tell you when your command is clicked, when another is clicked, and also to tell FreeCAD is your command has to be enabled or disabled.
You can test this in a macro by creating "manually" a command, without need to create a full workbench environment.
Sorry, what would solve the problem? I mean when you said same as the above, I thought you meant that it's not possible?
Using "Command" type would solve this too.
User avatar
ifohancroft
Posts: 205
Joined: Fri May 31, 2019 11:25 pm
Location: Sofia, Bulgaria
Contact:

Re: How to select a point on Sketcher's screen for use in a macro?

Post by ifohancroft »

openBrain wrote: Mon Sep 27, 2021 1:04 pm
ifohancroft wrote: Mon Sep 27, 2021 11:22 am No. I am trying to figure out if a sketch still exists so I don't try to execute my code if the sketch got deleted. However, I can't use ActiveSketch to check for that, because apparently it still holds the sketch object, even after the sketch is deleted.
Would need to know which information you have as a reference.
You can test with something like :

Code: Select all

hasattr(App.ActiveDocument, "SKETCHNAME")
Sorry. What do you mean by which information I have as a reference? Currently, I was executing

Code: Select all

ActiveSketch
in the python console to check whether it's still an object or if I'd get an error.

Is there a way to do it without having to have the sketch's name? I am looking for a more generic way to find out if there is an active sketch before I start drawing. I would have just checked if 'ActiveSketch' exists, but it doesn't get deleted even when you delete the only sketch in the document.


3. I am trying to imitate Sketcher's own tools with this macro, so I've made it that once you start it, you can keep clicking in the document and it will keep "drawing", unless you hit the right mouse button. Hitting the right mouse button shows the context menu on screen. Is there a way to prevent the context screen from showing when hitting the right mouse button while the macro is working?
AFAIK you can't prevent context menu to appear
You are right. The context menu still appears even after fixing the macro to actually exit.


Also, I just discovered that hitting the right mouse button doesn't actually stop the macro. Am I removing the event callback the wrong way?
Yes, your line should be

Code: Select all

self.view.removeEventCallback("SoMouseButtonEvent", self.view_callback)
Thank you! That did it.


Do you happen to know if input and tools are handled differently when writing a workbench (in Python)? Like would I have access to more events there? Such as when another tool gets selected or have access to the mouse coordinates and click events without needing to add a ViewObserver as a callback to the view? etc.. So I can make the tools appear more native?
In a certain way, you have access to more events. In a workbench, you will use "Command" type to create the toolbar features. There will so be a mechanism that will tell you when your command is clicked, when another is clicked, and also to tell FreeCAD is your command has to be enabled or disabled.
You can test this in a macro by creating "manually" a command, without need to create a full workbench environment.
Thank you! I will look into that.


Sorry, what would solve the problem? I mean when you said same as the above, I thought you meant that it's not possible?
Using "Command" type would solve this too.
Ah! Got it. Thank you!
I like making, breaking and modding stuff, using a soldering iron, code or both. https://ifohancroft.com
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: How to select a point on Sketcher's screen for use in a macro?

Post by openBrain »

ifohancroft wrote: Mon Sep 27, 2021 1:29 pm Sorry. What do you mean by which information I have as a reference? Currently, I was executing

Code: Select all

ActiveSketch
in the python console to check whether it's still an object or if I'd get an error.

Is there a way to do it without having to have the sketch's name? I am looking for a more generic way to find out if there is an active sketch before I start drawing. I would have just checked if 'ActiveSketch' exists, but it doesn't get deleted even when you delete the only sketch in the document.
Actually "ActiveSketch" doesn't have more sense. It is a variable used by the visibility automation mechanism but you shouldn't rely on this for a macro.
You have to define a criteria for the sketch you want to process. Is it the sketch currently in edition (if exist) ? Is it the selected sketch in the tree (if exist) ? Is it the last created sketch ? ... ?
User avatar
ifohancroft
Posts: 205
Joined: Fri May 31, 2019 11:25 pm
Location: Sofia, Bulgaria
Contact:

Re: How to select a point on Sketcher's screen for use in a macro?

Post by ifohancroft »

openBrain wrote: Mon Sep 27, 2021 1:32 pm
ifohancroft wrote: Mon Sep 27, 2021 1:29 pm Sorry. What do you mean by which information I have as a reference? Currently, I was executing

Code: Select all

ActiveSketch
in the python console to check whether it's still an object or if I'd get an error.

Is there a way to do it without having to have the sketch's name? I am looking for a more generic way to find out if there is an active sketch before I start drawing. I would have just checked if 'ActiveSketch' exists, but it doesn't get deleted even when you delete the only sketch in the document.
Actually "ActiveSketch" doesn't have more sense. It is a variable used by the visibility automation mechanism but you shouldn't rely on this for a macro.
You have to define a criteria for the sketch you want to process. Is it the sketch currently in edition (if exist) ? Is it the selected sketch in the tree (if exist) ? Is it the last created sketch ? ... ?
Ah, yeah! My criteria is the sketch currently being in edition (if it exists)
I like making, breaking and modding stuff, using a soldering iron, code or both. https://ifohancroft.com
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: How to select a point on Sketcher's screen for use in a macro?

Post by openBrain »

ifohancroft wrote: Mon Sep 27, 2021 1:43 pm
openBrain wrote: Mon Sep 27, 2021 1:32 pm
ifohancroft wrote: Mon Sep 27, 2021 1:29 pm Sorry. What do you mean by which information I have as a reference? Currently, I was executing

Code: Select all

ActiveSketch
in the python console to check whether it's still an object or if I'd get an error.

Is there a way to do it without having to have the sketch's name? I am looking for a more generic way to find out if there is an active sketch before I start drawing. I would have just checked if 'ActiveSketch' exists, but it doesn't get deleted even when you delete the only sketch in the document.
Actually "ActiveSketch" doesn't have more sense. It is a variable used by the visibility automation mechanism but you shouldn't rely on this for a macro.
You have to define a criteria for the sketch you want to process. Is it the sketch currently in edition (if exist) ? Is it the selected sketch in the tree (if exist) ? Is it the last created sketch ? ... ?
Ah, yeah! My criteria is the sketch currently being in edition (if it exists)
So I already replied with this link : https://forum.freecadweb.org/viewtopic. ... 57#p418157
It's doable with :

Code: Select all

if Gui.ActiveDocument.getInEdit().Object.isDerivedFrom("Sketcher::SketchObject"):
    sketchPointer = Gui.ActiveDocument.getInEdit().Object
User avatar
ifohancroft
Posts: 205
Joined: Fri May 31, 2019 11:25 pm
Location: Sofia, Bulgaria
Contact:

Re: How to select a point on Sketcher's screen for use in a macro?

Post by ifohancroft »

openBrain wrote: Mon Sep 27, 2021 1:48 pm
ifohancroft wrote: Mon Sep 27, 2021 1:43 pm
openBrain wrote: Mon Sep 27, 2021 1:32 pm
ifohancroft wrote: Mon Sep 27, 2021 1:29 pm Sorry. What do you mean by which information I have as a reference? Currently, I was executing

Code: Select all

ActiveSketch
in the python console to check whether it's still an object or if I'd get an error.

Is there a way to do it without having to have the sketch's name? I am looking for a more generic way to find out if there is an active sketch before I start drawing. I would have just checked if 'ActiveSketch' exists, but it doesn't get deleted even when you delete the only sketch in the document.
Actually "ActiveSketch" doesn't have more sense. It is a variable used by the visibility automation mechanism but you shouldn't rely on this for a macro.
You have to define a criteria for the sketch you want to process. Is it the sketch currently in edition (if exist) ? Is it the selected sketch in the tree (if exist) ? Is it the last created sketch ? ... ?
Ah, yeah! My criteria is the sketch currently being in edition (if it exists)
So I already replied with this link : https://forum.freecadweb.org/viewtopic. ... 57#p418157
It's doable with :

Code: Select all

if Gui.ActiveDocument.getInEdit().Object.isDerivedFrom("Sketcher::SketchObject"):
    sketchPointer = Gui.ActiveDocument.getInEdit().Object
Thank you!

I am not sure if the Solved in the title is required or even helpful, but I am marking it as solved as, well I got the answer to everything, not just the question in the topic.

Thank you!
I like making, breaking and modding stuff, using a soldering iron, code or both. https://ifohancroft.com
Post Reply