(2.79) Which button in a panel I'm hovering over

Alright, so, I have a panel in properties with a box and some buttons spawned through layout.operator

I have this already set up so that I will know if I’m hovering over a button. No problem.
I can get the mouse coordinates, no problem either.

If I knew the coordinates of that button, my problem is solved. So, can I get that?

Just need to drag a box up and down, no rocket science here. It already works as intended if I call the operator directly. Now all I want is to call the same operator when I hover and hold down left click.

Sorry to bump so early but dropping an example so people know what I’m talking about

I need a grip for this custom list and as you can see I already have the logic down. So what’s the problem? The modal operator here only invokes after the user clicks the button and releases. I need to activate it on first click, drag to resize, and stop the operator when the left mouse button is released.

As it is now, you click and release to start resizing, resize, then click again to stop. Awkward much? It’s a similar case for the scrollbar (yeah, I did the scrollbar too, and you can’t drag it either; it’s all buttons).

So I need to start listening for events as soon as the mouse is on the button and launch the operator manually, that’s not really a problem. But if I’m unable to tell which button I’m hovering, that’s as far as I can go.

I could manually calculate the position of the widget from region position, height and width, but if I add more panels then that approach fails as soon as the user shuffles them around.

All in all, just the mere confirmation that what I want to do is not possible is good enough at this point. That at least I can rub in a dev’s face! Hehe.

No way to get the contents of the UI. Since Blender is designed as an MVC architecture, it means that the “C” (you are currently working on – the operator) will know nothing about the “V” (how things rendered).

This is a genius design in many ways, it allows you to do lots of complex and difficult stuff, but as a side effect the limitations are that you can’t do even the most simple stuff.

So this means that you will have to keep trying to find hacks on how to fake many behaviors like these. While in some other GUI paradigm you could do something in a straight line, with Blender you need to go in circles to achieve that.

One way is this. Not to mention that this is the right way or the proper way. But technically speaking it allows you do perform code execution when you need it. You simulate the mouse hover event yourself. :slight_smile:

import bpy


class TheButtonPanel(bpy.types.Panel):
    bl_label = "Layout Demo"
    bl_idname = "SCENE_PT_layout_button"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "scene"
    
    def draw(self, context):
        layout = self.layout
        row = layout.row()
        row.scale_y = 3.0
        row.operator("render.render")
        for i in range(10):
            print('running the code')

class LayoutDemoPanel(bpy.types.Panel):
    """Creates a Panel in the scene context of the properties editor"""
    bl_label = "Layout Demo"
    bl_idname = "SCENE_PT_layout"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "scene"
    
    def draw(self, context):
        layout = self.layout
        layout.label(text="Normal Button")
        layout.operator("render.render")
        layout.separator()
        layout.popover(panel="SCENE_PT_layout_button")

def register():
    bpy.utils.register_class(LayoutDemoPanel)
    bpy.utils.register_class(TheButtonPanel)
    
def unregister():
    bpy.utils.unregister_class(LayoutDemoPanel)
    bpy.utils.unregister_class(TheButtonPanel)

if __name__ == "__main__":
    try:unregister()
    except:pass
    print('registered panels')
    register()

Seems to work but I don’t get UIPopover in 2.79 so I’m seeing the abridged version here. And two panels with the same name :B

seeing_double

But let’s see if I get it: you have a draw that does nothing but one button so on every call you know exactly which button was redrawn? That’s pretty ingenious. Though if I can’t roll both panels into one it might be more awkward that it already is.

I wouldn’t dare argue against the genius of Blender, but I am pretty salty about this one! haha

Oh, unfortunately this code runs on 2.8, popover must be a new thing.

Perhaps you could find something else here.

https://docs.blender.org/api/2.79/bpy.types.UILayout.html#bpy.types.UILayout

How about going with a menu instead?
You can turn the panel class of that button into a menu class and append it from layout.

See Template > Python > UI Menu
class CustomMenu(bpy.types.Menu):

But you got the the idea, it means that the panel will run the code once the panel class is drawn, hopefully this is done only once in the case of popover. I think it might work the same for menu.

Mmmh, can’t get it to work quite right with a menu but I’ll see what else I can try. As a last resot alternative, I have the sources so I could try digging through and cook my own solution in C. But that may get crazy as I don’t want to distribute a separate build, just some .py files and a couple .dlls at most, so I can’t make changes to Blender itself for this. Aah, we’ll see.