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 — imgui prototype by kushalkolar · Pull Request #552 · fastplotlib/fastplotlib

Conversation

@kushalkolar

@kushalkolar kushalkolar commented Jul 11, 2024 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Member

Very early dirty prototype, works in qt windows and gridplots, glfw is crashing for some reason.

We also need to figure out the big-picture of how we implement it, and sequester it. There will always be people who just want to use Qt or some other framework for making their UI. If someone doesn't want to make their UI they can use the built-in imgui, otherwise they don't need to install imgui and can use their preferred framework :D

Can probably have a UIBaseClass for all imgui UIs that fastplotlib uses, and Figure will take an instance of UIClass as an instance and call the UIClass.update() method. Figure will give it the font and any other config, such as the canvas, maybe makes a unique ID_COUNTER for each UIClass instance? See if having multiple ID_COUNTER that all have diff start addresses works so that user-implemented UIs don't have to worry about pushing ids.

Relies on pygfx/wgpu-py#539

image

ImageWidget:

imgui-2024-07-11_21.50.32.mp4

Sorry, something went wrong.

Uh oh!

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

All reactions
kushalkolar added 3 commits July 11, 2024 05:54
@kushalkolar
imgui prototype, works in qt windows and gridplots
911a79c
@kushalkolar
works in multiple figs and canvas :D
2265255
@kushalkolar
imagewidget sliders
d9da6eb
@kushalkolar

kushalkolar commented Jul 12, 2024 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Member Author

Discussion with @clewis7

  • hlut colorbar right click, choose cmap from big dropdown with pictures and names of cmaps
  • right click menu in subplots
    • All the toolbar options
    • clear subplot -> with confirm popup
    • clear figure -> with confirm popup
    • Graphics list submenu, clicking it opens a small window with info and ability to change stuff, this window has:
      • Buttons to add diff selectors -> when clicked, it asks for a name for the selector
      • button to delete_graphic -> with confirm popup
      • lineedit to change name
      • other properties, rotation, offset
      • graphic specific options
    • controller options, shows a small window kinda like the pyqtgraph one
      • include/exclude filters for each axis
      • damping
  • Record button toolbar and option in right-click menu
    • pops up a window with options for recording
      • path, codec, quality, etc....
  • screenshot, both toolbar and right click menu
  • Axes
    • tick stuff
      • spacing, font size, etc.
    • visible for each dimension
    • grid
      • visible for each plane
      • major and minor step

Idea for managing/sequestering: subclass Figure into a new class FigureWithImgui with the following structure:

class ImguiFigure
def __init__(self, *args, **kwargs):
    super()
    self.imgui_renderer ....
    # more imgui init stuff
    self._guis = list()

def render(self):
    super()
    # imgui render stuff
    for gui in self.guis:
        gui.update()
    imgui.end_frame()
    ...
    canvas.request_draw()

def add_ui(self, edge: str, callable_or_instance_TBD):  # edge is the top, bottom, left, or right edge of the canvas
    # parse edge and set Figure bbox, i.e. [x, y, width, height] that the pygfx renderer uses
    self._guis["edge"] = callable_or_instance_TBD

def set_ui_size(self, edge: str, size: int):
    # set imgui reserved size
    self._edges["edge"].size = size

@property
def width(self) -> int
    return self.renderer.logical_size[0] - self._edges["left"] -self._edges["right"]

# likewise properties for height, x, and y
# use these [x, y, width, height] properties elsewhere in the `Figure`
# such as the subplots and other `PlotAreas` instead of `renderer.logical_size`

Determine whether to import FigureBasic or FigureWithImgui similar to how the jupyter, qt, glfw import is done.

All reactions

Sorry, something went wrong.

Uh oh!

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

@kushalkolar

kushalkolar commented Jul 13, 2024

Copy link
Copy Markdown
Member Author

Something we will have to solve with right click menus, if an item in the right click menu is clicked we have to stop that click event from propagating to the pygfx stuff below the menu. See if imgui can do pointer capture.

All reactions

Sorry, something went wrong.

Uh oh!

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

@kushalkolar
begin right click menu
a8e566a
@kushalkolar

kushalkolar commented Jul 14, 2024

Copy link
Copy Markdown
Member Author

Idea: use imgui for the legends since it already has layouting etc for this type of use case. But then we're forcing people to use imgui. Will think more about this.

All reactions

Sorry, something went wrong.

Uh oh!

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

@kushalkolar

kushalkolar commented Jul 14, 2024

Copy link
Copy Markdown
Member Author

Maybe instead of letting imgui detect and handle the right click event for creating the right click menu popup: add an event handler to the renderer and any graphics for which we want specific right click events. Have them add to a "request queue", for example right click on hlut tool colorbar will request a specific popup menu to be shown on the next render cycle. In each render cycle we go through the queue. Will need to see if we can execute all items in the queue, or if we just do the first one and discard the rest? This might get messy...

All reactions

Sorry, something went wrong.

Uh oh!

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

@kushalkolar

kushalkolar commented Jul 15, 2024

Copy link
Copy Markdown
Member Author

Right click menu for hlut tool to reset vmin vmax

All reactions

Sorry, something went wrong.

Uh oh!

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

@kushalkolar
changes
844858b
@kushalkolar kushalkolar mentioned this pull request Jul 18, 2024
Develop a proof-of-concept prototype for a web-based graphical interface neuroinformatics-unit/movement#164
Open
@kushalkolar

kushalkolar commented Jul 19, 2024

Copy link
Copy Markdown
Member Author

We can use the imgui windows to set the viewport rect of subplots, just an idea for the future, needs more protyping & thought to implement. Not committed to this. Might be better to handle moving and resizing subplots directly via pygfx, perhaps after the viewports & renderers refactor.

playing_imgui-2024-07-19_00.51.20.mp4

Messy implemention:

  1. remove the width and height spacings from _subplot
  2. add this to Figure.__init__: io.config_windows_move_from_title_bar_only = True

subplot toolbar:

from imgui_bundle import imgui, icons_fontawesome_6 as fa, imgui_ctx

from .._plot_area import PlotArea


ID_COUNTER = 0


class SubplotToolbar:
    def __init__(self, subplot: PlotArea, icons: imgui.ImFont):
        self._subplot = subplot
        self.icons = icons

        # required to prevent conflict with multiple Figures
        global ID_COUNTER
        ID_COUNTER += 1

        self.id = ID_COUNTER

        self.bbox = subplot.get_rect()
        self._subplot.get_rect = self.get_rect

    def get_rect(self):
        x, y, width, height = self.bbox

        return x + 10, y + 50, width - 10, height - 60

    def update(self):
        x, y, width, height = self._subplot.get_rect()

        # pos = (x, y + height)

        size = self.bbox[2:]
        pos = self.bbox[:2]

        imgui.set_next_window_size(size, imgui.Cond_.appearing)
        imgui.set_next_window_pos(pos, imgui.Cond_.appearing)
        flags = imgui.WindowFlags_.no_collapse | imgui.WindowFlags_.no_background #| imgui.WindowFlags_.no_title_bar

        imgui.begin(f"Toolbar-{self._subplot.position}", p_open=None, flags=flags)

        width, height = imgui.get_window_size()
        x, y = imgui.get_window_pos()


        imgui.push_font(self.icons)

        imgui.push_id(self.id)  # push ID to prevent conflict between multiple figs with same UI
        with imgui_ctx.begin_horizontal(f"toolbar-{self._subplot.position}"):
            # autoscale button
            if imgui.button(fa.ICON_FA_MAXIMIZE):
                self._subplot.auto_scale()
            imgui.pop_font()
            if imgui.is_item_hovered(0):
                imgui.set_tooltip("autoscale scene")

            # center scene
            imgui.push_font(self.icons)
            if imgui.button(fa.ICON_FA_ALIGN_CENTER):
                self._subplot.center_scene()

            # checkbox controller
            _, self._subplot.controller.enabled = imgui.checkbox(fa.ICON_FA_COMPUTER_MOUSE, self._subplot.controller.enabled)

            # checkbox maintain_apsect
            _, self._subplot.camera.maintain_aspect = imgui.checkbox(fa.ICON_FA_EXPAND, self._subplot.camera.maintain_aspect)

            imgui.pop_font()

            _, flip_y = imgui.checkbox("flip-y", self._subplot.camera.local.scale_y < 0)
            if flip_y and self._subplot.camera.local.scale_y > 0:
                self._subplot.camera.local.scale_y *= -1
            elif not flip_y and self._subplot.camera.local.scale_y < 0:
                self._subplot.camera.local.scale_y *= -1

        imgui.pop_id()

        self.bbox = (x, y, width, height)
        self._subplot.set_viewport_rect()

        imgui.end()
All reactions

Sorry, something went wrong.

Uh oh!

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

@kushalkolar kushalkolar closed this Jul 19, 2024
@kushalkolar kushalkolar reopened this Jul 19, 2024
@kushalkolar

kushalkolar commented Jul 19, 2024

Copy link
Copy Markdown
Member Author

@clewis7 let's forget about using imgui to control subplot viewports etc. for this year, we can just focus on the ideas outlined above in #552 (comment) , i.e. toolbar, imagewidget stuff, sequester imgui, and have a way for users to add their own UI on one of the canvas edges. I think that's enough for now and plenty.

Controlling subplot viewports like this and other things open up a can of worms, scope explosion, and change how the whole fpl API works. We can think about it next year?

All reactions

Sorry, something went wrong.

Uh oh!

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

@kushalkolar

kushalkolar commented Jul 28, 2024

Copy link
Copy Markdown
Member Author

We can use the imgui windows to set the viewport rect of subplots, just an idea for the future, needs more protyping & thought to implement. Not committed to this. Might be better to handle moving and resizing subplots directly via pygfx, perhaps after the viewports & renderers refactor.

I have an idea to build upon this, user could right click -> drag to draw a rectangle, and then this rectangle becomes a new subplot on an empty figure canvas 😆

All reactions

Sorry, something went wrong.

Uh oh!

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

kushalkolar added 4 commits July 28, 2024 07:16
@kushalkolar
very functional right-click menu, depends on my pygfx.WgpuRenderer ev…
fdc1f95
…ents filter
@kushalkolar
use WgpuRenderer subclass until pygfx refactors update propogation
6573d7d
@kushalkolar
some fixes
ae0e53d
@kushalkolar
axis flipping and FOV options in right click menu
0b6bca3
@kushalkolar

kushalkolar commented Jul 30, 2024

Copy link
Copy Markdown
Member Author

superseeded by #571

All reactions

Sorry, something went wrong.

Uh oh!

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

@kushalkolar kushalkolar closed this Jul 30, 2024
@kushalkolar
kushalkolar deleted the imgui branch October 7, 2024 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@clewis7 clewis7 Awaiting requested review from clewis7 clewis7 will be requested when the pull request is marked ready for review clewis7 is a code owner

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.

1 participant

@kushalkolar
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.