GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — cursor tool and better tooltips by kushalkolar · Pull Request #947 · fastplotlib/fastplotlib

Conversation

@kushalkolar

@kushalkolar kushalkolar commented Nov 19, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

This ended up being more than just the cursor tool since I needed to do a few other things to make this work well 😆

Transforms

This PR adds useful functions to Graphic. map_model_to_world() and the inverse map_world_to_model(): https://github.com/fastplotlib/fastplotlib/pull/947/changes#diff-a57994ecff1cde4e05c8175265219f0b5200da144ce8733b9eb560c09bcea7ddR501-R558

This lets you map model/data space <-> world space. It accounts for any transforms (translation, i.e. Graphic.offset, scale and rotation) and maps the actual data position to world space.

Graphic.scale is a new graphic feature.

I added examples that show how all these transforms relate to each other, and how to map between them. They are in examples/space_transforms

I now forgot why I added map model <-> world, but I'm sure they will be useful 😅 .

I also added PlotArea.map_world_to_screen(), which is the inverse of map_screen_to_world(). The Cursor uses this in the following way to display tooltips in other subplots:

  1. Pointer is at a certain location in Subplot 1. We know the world space position of the pointer at this location, draw the Cursor at this location in Subplot 1. Since the pointer is over this location, we can also draw a tooltip here. Tooltips are drawn in the overlay render pass and are therefore always in screen space.
  2. Now we need to draw the cursor at the same world space location in all other subplots, this is simple. But we need the screen space positions for the corresponding world space positions in these other subplots. So we use map_world_to_screen() to know where to draw the tooltip in these other subplots. This is also used to get the pick info at this screen position.

Tooltip

Created TextBox, which is a simple text box object. Tooltip inherits from TextBox and just adds a few uesful properties.

The tooltips are managed by PlotArea, see code review comments for an explanation.

Map WorldObject -> Graphic

I created a dict that maps world object id -> Graphic.

https://github.com/fastplotlib/fastplotlib/pull/947/changes#diff-a57994ecff1cde4e05c8175265219f0b5200da144ce8733b9eb560c09bcea7ddR40-R42

Useful when manually picking the picking Texture to get picking info about a certain screen position (ex: Cursor tool to get pick info other subplots). Also used to get the pick info when updating the tooltip on every render.

Cursor

A simple cursor tool, has two modes "crosshair" which uses 2 infinite lines, and "marker" that uses a pygfx point with marker material.

This just maps the same position in world space across all subplots. I think we should keep it simple this way, unlike the ideas proposed in #662 .

Size, color, etc. are settable properties.

The cursor also sets the tooltip in other subplots that have been added to the cursor! Since we know the world space position in all other subplots, we can map_world_to_screen() and get the pick info for that position in the other subplot, and then display the tooltip in the other subplots with that pick info https://github.com/fastplotlib/fastplotlib/pull/947/changes#diff-dfc9ee2c327058ca7075a70aed1eb973aeb47e1e08e65a67c512a318ed6036aeR254-R257

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@kushalkolar
new cursor tool, basics work
97442f5
@kushalkolar
kushalkolar requested a review from clewis7 as a code owner November 19, 2025 12:51
@kushalkolar kushalkolar mentioned this pull request Nov 19, 2025
Cursor tool #662
Closed
4 of 14 tasks
@clewis7
lint and update api docs
034f719
@github-actions

github-actions Bot commented Nov 19, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

📚 Docs preview built and uploaded! https://www.fastplotlib.org/ver/cursor-simpler

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

clewis7
clewis7 reviewed Nov 19, 2025
View reviewed changes

@clewis7 clewis7 left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kushalkolar general comments to make sure everything is properly documented/commented etc.

I know you want to merge this today, besides one logic issue with the mode, it looks good to me

The other things are less critical and can be updated in another PR. I just wanted to document them. I went ahead and linted and added the doc updates so everything would pass.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread examples/misc/cursors.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread fastplotlib/tools/_cursor.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread fastplotlib/tools/_cursor.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread fastplotlib/tools/_cursor.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread fastplotlib/tools/_cursor.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

kushalkolar added 5 commits November 19, 2025 22:54
@kushalkolar
add custom tooltip to figure
9a18381
@kushalkolar
Merge branch 'cursor-simpler' of https://github.com/fastplotlib/fastp…
b08e744
…lotlib into cursor-simpler
@kushalkolar
example WIP
cf0c6dd
@kushalkolar
manual picking, world obj -> graphic mapping
86807c2
@kushalkolar
fix
506fa2c
@kushalkolar

kushalkolar commented Nov 20, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

This is gonna need a bit more work.

Display tooltip at corresponding location in other subplots by manually picking at that location to get the info about the graphic at that location.

Basically:

If system cursor is on subplot A, and we want to display tooltip at same world space location in subplot B:

# system cursor over position in subplot A, get world pos
pos = subplot_A.map_screen_to_world(ev)

# get corresponding screen space position in subplot B
x, y = subplot_B.map_world_to_screen(pos)
# get pick info of this screen pixel
pick = subplot.get_pick_info((x, y))

if pick is None:  # no graphic at this screen pixel in subplot B
    tooltips2.visible = False
    return

# display graphic metadata or anyrelevant info in the tooltip in subplot B
info = pick["graphic"].metadata
tooltips2.display((x, y), str(info))
manual_picking-2025-11-20_04.29.45.mp4
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

kushalkolar
kushalkolar commented Nov 20, 2025
View reviewed changes
Comment thread fastplotlib/graphics/_base.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@kushalkolar
fix gc
f69ccc9
@kushalkolar

kushalkolar commented Nov 20, 2025

Copy link
Copy Markdown
Member Author

@clewis7 I'm thinking about changing who "owns" tooltips. Right now Figure owns tooltips and can auto-display them. I'm thinking of a tooltip being owned by each Subplot instead, so we can have a method:

Subplot.display_tooltip(pos: tuple[float, float], space: Literal["world", "screen"], info: str):
    ...

Tooltips are drawn in the overlay render pass which is in screen space, so the tooltip position in the end always has to be in screen space. However it is useful to think of them in world space since that's where the graphics are. It'll just be much easier to know the position of a graphic in world space where you want to show the tooltip, and the Subplot.display_tooltip() will project that pos to screen space under automatically.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@kushalkolar kushalkolar changed the title new cursor tool, basics work cursor tool and better tooltips Nov 21, 2025
@clewis7

clewis7 commented Nov 21, 2025

Copy link
Copy Markdown
Member

@clewis7 I'm thinking about changing who "owns" tooltips. Right now Figure owns tooltips and can auto-display them. I'm thinking of a tooltip being owned by each Subplot instead, so we can have a method:

Subplot.display_tooltip(pos: tuple[float, float], space: Literal["world", "screen"], info: str):
    ...

Tooltips are drawn in the overlay render pass which is in screen space, so the tooltip position in the end always has to be in screen space. However it is useful to think of them in world space since that's where the graphics are. It'll just be much easier to know the position of a graphic in world space where you want to show the tooltip, and the Subplot.display_tooltip() will project that pos to screen space under automatically.

And why would tooltips not be owned by the graphic they correspond to? I could also imagine a property that is image_graphic.tooltip.display = False

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@kushalkolar

kushalkolar commented Nov 21, 2025

Copy link
Copy Markdown
Member Author

And why would tooltips not be owned by the graphic they correspond to? I could also imagine a property that is image_graphic.tooltip.display = False

I didn't think of that! This might be a better way to do it, and customization of tooltips per-graphic makes most sense I think.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@clewis7

clewis7 commented Nov 21, 2025

Copy link
Copy Markdown
Member

I didn't think of that! This might be a better way to do it, and customization of tooltips per-graphic makes most sense I think.

I think then, if you wanted to not display all of the tooltips for graphics in the subplot, you would just need to iterate:

for g in subplot.graphics:
     g.tooltip.display = False 
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

kushalkolar added 4 commits November 25, 2025 14:50
@kushalkolar
stuff
c0c1203
@kushalkolar
Merge branch 'main' into cursor-simpler
cbc5127
@kushalkolar
Merge branch 'cursor-simpler' of https://github.com/fastplotlib/fastp…
5630f23
…lotlib into cursor-simpler
@kushalkolar
cursor and tooltips refactor, basically works
c5f8eac
@kushalkolar

kushalkolar commented Dec 6, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

ok all this stuff works now:

tooltips update on every render, useful when data under the cursor changes:

tooltips-update-2025-12-06_05.14.36.mp4

Tooltips are now enabled on graphics by default, and a cursor can trigger a tooltip to show up in other subplots:

cursor-tooltips-2025-12-06_05.46.04.mp4

Added more mapping functions, these are explained in the guide:

- ``Subplot.map_screen_to_world((x, y))``
- ``Subplot.map_world_to_screen((x, y, z))``
- ``Graphic.map_model_to_world((x, y, z))``
- ``Graphic.map_world_to_model((x, y, z))``

Need to test a bit, add some more examples maybe, and possibly cleanup some of the code if it can be simplified.

Need to add tests to make sure the right default tooltip display comes up for all graphics.

I should add examples that explain all the spaces (model, world, screen) using a variety of graphics. Show a few points on the graphic and put text that indicates model, world and screen space positions.

  • Graphic that isn't rotated or scaled, model and world are same
  • Graphic scaled
  • Graphic rotated
  • Graphic scaled, rotated, translated

Do this with Image, Line and an ellipsoid, should be enough.

@clewis7 you can take a look, but I'm guessing you're deep in CPU design optimizations for the next few days 😆 . I'll summarize everything in this PR later, required quite a bit more than I thought to get this to work.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@kushalkolar

kushalkolar commented Dec 7, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

OK things getting slightly messy, I think this will be better:

  • TextBox that can be used to display a textbox anywhere, just text with a rectangle mesh behind it. Lives in the overlay scene.
  • Tooltip is a subclass of TextBox. One tooltip instance always exists per subplot. Graphic.tooltip merely sets the tooltip in its subplot.

The PlotArea could also update its tooltip with whatever pick info is under a pixel on every render.

Perhaps the renderer "pointer_move" event could just be used to set the tooltips in each subplot by getting the graphic from the pick_info at that position.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

kushalkolar added 2 commits December 7, 2025 02:07
@kushalkolar
much simpler tooltip and cursor
9323e3a
@kushalkolar
move TextBox and Tooltip, update API docs
a59f686
@kushalkolar

kushalkolar commented Dec 7, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

I think things are much simpler now.

  • Created TextBox class
  • Tooltip which is a light subclass of TextBox
  • PlotArea has a Tooltip instance as an attribute. "pointer_move" events will set the tooltip.
  • if Tooltip.continuous_mode, then PlotArea will update the tooltip on every render
  • Cursor uses Subplot.get_pick_info() to get the graphic, pick info, and set the tooltip in that subplot.

One thing left out is I need to think of how to set the tooltip w.r.t. the transform when it's on the current subplot with a cursor. Figured it out, let the cursor manage tooltips entirely when a subplot is added to it.

cursor-tooltips-2025-12-07_03.43.05.mp4
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

kushalkolar added 2 commits December 7, 2025 03:42
@kushalkolar
cursor manages tooltips
c60f1fe
@kushalkolar
update examples
32493b1
@kushalkolar

kushalkolar commented Dec 17, 2025

Copy link
Copy Markdown
Member Author

For the examples to demonstrate the different spaces I think I'll make one example for each of these (instead of separate subplots in one Figure) and two sets, one with an image and one with a line:

  • no transforms
  • translation
  • scaling
  • rotation
  • translation + scaling
  • translation + scaling + rotation
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

kushalkolar added 13 commits December 16, 2025 23:18
@kushalkolar
add image space transforms examples
6d535e7
@kushalkolar
finish space transforms examples
00b51a9
@kushalkolar
typing
1cafa74
@kushalkolar
black
f585007
@kushalkolar
docstrings
a64ce67
@kushalkolar
update examples
a0f74c2
@kushalkolar
textbox constructor takes args, docstrings
6a648e7
@kushalkolar
True -> true
dd65092
@kushalkolar
update names
cd0f216
@kushalkolar
update cursor examples
70c8088
@kushalkolar
new ground truth screenshots for transforms
d4c3eb7
@kushalkolar
black
edca694
@kushalkolar
update
3570fba
kushalkolar
kushalkolar commented Dec 17, 2025
View reviewed changes
Comment thread fastplotlib/layouts/_plot_area.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread fastplotlib/layouts/_plot_area.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread fastplotlib/graphics/_base.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread fastplotlib/layouts/_plot_area.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@kushalkolar
revert persist kwarg in PlotArea animations stuff
a7bf44c
@kushalkolar

kushalkolar commented Dec 17, 2025

Copy link
Copy Markdown
Member Author

@clewis7 finally r4r! And just before midnight here 😂

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@kushalkolar

kushalkolar commented Dec 18, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

There is a bug in Volume, will figure out.

Edit: this is a pygfx thing, posted: pygfx/pygfx#1251

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

kushalkolar added 2 commits December 21, 2025 23:46
@kushalkolar
fix
fba5247
@kushalkolar
message for image volumes
201b75c
@kushalkolar

kushalkolar commented Dec 22, 2025

Copy link
Copy Markdown
Member Author

Until pygfx/pygfx#1253 is in the next release of pygfx I've kinda disabled tooltips for ImageVolume.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

clewis7
clewis7 previously approved these changes Jan 14, 2026
View reviewed changes

@clewis7 clewis7 left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@clewis7 @kushalkolar
Update fastplotlib/graphics/_base.py
32c7d5f
Co-authored-by: Kushal Kolar <[email protected]>
@clewis7
clewis7 dismissed their stale review via 32c7d5f January 14, 2026 16:45
clewis7
clewis7 approved these changes Jan 14, 2026
View reviewed changes
@clewis7
clewis7 merged commit 7075e46 into main Jan 14, 2026
72 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@clewis7
clewis7 deleted the cursor-simpler branch January 14, 2026 17:18
@kushalkolar kushalkolar mentioned this pull request Feb 17, 2026
setting initial scale was missing from Graphic._set_world_object #993
Merged
@kushalkolar kushalkolar mentioned this pull request Mar 5, 2026
Easier way to create custom imgui right-click menus for graphics #1010
Closed
@kushalkolar kushalkolar mentioned this pull request Sep 1, 2026
Roadmap 2026 #55
Open
54 of 78 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@almarklein almarklein almarklein left review comments
@clewis7 clewis7 clewis7 approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@kushalkolar @clewis7 @almarklein
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.