Skip to content

Commit

Permalink
Better handling of Remote Panel display and minor bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
mmmrqs committed Oct 31, 2021
1 parent f7370e1 commit 49ca3fb
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 26 deletions.
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
# Note: Because the way Blender's Preferences window displays the Addon version number,
# I am forced to keep this file in sync with the greatest version number of all modules.

# v1.0.2 (09.30.2021) - by Marcelo M. Marques
# v1.0.2 (10.31.2021) - by Marcelo M. Marques
# Chang: updated version with improvements and some clean up

# v1.0.1 (09.20.2021) - by Marcelo M. Marques
Expand Down
2 changes: 1 addition & 1 deletion bl_ui_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

# --- ### Change log

# v1.0.2 (09.30.2021) - by Marcelo M. Marques
# v1.0.2 (10.31.2021) - by Marcelo M. Marques
# Chang: improved reliability on 'mouse_down' and 'mouse_up' overridable functions by conditioning the returned value

# v1.0.1 (09.20.2021) - by Marcelo M. Marques
Expand Down
73 changes: 62 additions & 11 deletions bl_ui_draw_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@

# --- ### Change log

# v1.0.2 (09.30.2021) - by Marcelo M. Marques
# v1.0.2 (10.31.2021) - by Marcelo M. Marques
# Added: 'region_pointer' class level property to indicate the region in which the drag_panel operator instance has been invoked().
# Added: 'valid_modes' property to indicate the 'bpy.context.mode' valid values for displaying the panel.
# Added: 'valid_scenario' function to validate whether the events must be handled by the widgets during a modal pass.
# Added: 'get_region_pointer' function to retrieve the value of the 'region_pointer' class level property.
# Added: 'get_quadview_index' function to retrieve the region under which the mouse is hovering or being clicked.
# Added: 'get_3d_area_and_region' function to retrieve the correct area and region (because those are not guaranteed to remain
# the same after maximizing/restoring screen areas).
# Added: 'valid_display_mode' function to determine whether the user has moved out of the valid area/region.
Expand Down Expand Up @@ -156,15 +158,11 @@ def modal(self, context, event):
if self.__finished:
return {'FINISHED'}

area, region, abend = get_3d_area_and_region()

if abend:
self.finish()
if self.terminate_execution(area, region):
self.finish()
valid, area, region = self.valid_scenario(context, event)
if area:
area.tag_redraw()
if self.handle_widget_events(event):
if valid:
if self.handle_widget_events(event, area, region):
return {'RUNNING_MODAL'}

# Not using this escape option, but left it here for documentation purpose
Expand All @@ -173,7 +171,34 @@ def modal(self, context, event):

return {'PASS_THROUGH'}

def handle_widget_events(self, event):
def valid_scenario(self, context, event):
valid = True
area, region, abend = get_3d_area_and_region()
if abend:
self.finish()
valid = False
elif not (area and region):
# Return but do not finish
valid = False
elif self.terminate_execution(area, region):
area.tag_redraw()
self.finish()
valid = False
elif event.type != 'TIMER':
# Check whether it is drawing on the same region where the panel was initially opened
mouse_region = get_quadview_index(context, event.mouse_x, event.mouse_y)[0]
if mouse_region is None or mouse_region.as_pointer() != self.get_region_pointer():
# Not the same region, so skip handling events at this time
valid = False
return (valid, area, region)

def handle_widget_events(self, event, area, region):
# Consider not a valid display mode when the overridable custom function
# returns True (meaning that it wants to suppress the rendering anyway).
if event.type != 'TIMER':
if self.suppress_rendering(area, region):
return False

result = False
for widget in self.widgets:
if widget.visible or event.type == 'TIMER':
Expand Down Expand Up @@ -218,6 +243,15 @@ def draw_callback_px(self, op, context):
# -- end of the personalized criteria for the given addon --
return

# Check whether it is drawing on the same region where the panel was initially opened
for region in context.area.regions:
if region.type == 'WINDOW':
if context.region == region:
if region.as_pointer() != self.get_region_pointer():
# Not the same region, so skip drawing there
return
break

# This is to detect when user moved into an undesired 'bpy.context.mode'
# and it will check also the programmer's defined suppress_rendering function
if valid_display_mode(self.valid_modes, self.suppress_rendering):
Expand All @@ -227,6 +261,23 @@ def draw_callback_px(self, op, context):

# --- ### Helper functions

def get_quadview_index(context, x, y):
for area in context.screen.areas:
if area.type != 'VIEW_3D':
continue
is_quadview = (len(area.spaces.active.region_quadviews) == 0)
i = -1
for region in area.regions:
if region.type == 'WINDOW':
i += 1
if (x >= region.x and
y >= region.y and
x < region.width + region.x and
y < region.height + region.y):
return (region, area.spaces.active, None if is_quadview else i)
return (None, None, None)


def get_3d_area_and_region(prefs=None):
abend = False
try:
Expand Down Expand Up @@ -278,12 +329,12 @@ def valid_display_mode(valid_modes, suppress_rendering=None):
return False

area, region, abend = get_3d_area_and_region()
if abend:
if abend or not area or not region:
return False
else:
if suppress_rendering is not None:
# Consider not a valid display mode when the overridable custom function
# returns True (meaning that it wants to suppress the rendering at all).
# returns True (meaning that it wants to suppress the rendering anyway).
if suppress_rendering(area, region):
return False
return True
2 changes: 1 addition & 1 deletion bl_ui_slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

# --- ### Change log

# v1.0.2 (09.30.2021) - by Marcelo M. Marques
# v1.0.2 (10.31.2021) - by Marcelo M. Marques
# Added: 'valid_modes' parm in the 'init' function and a call to 'super().init_mode' so we get everything correctly initialized.
# Chang: improved reliability on 'mouse_exit' and 'button_mouse_down' overridable functions by conditioning the returned value

Expand Down
2 changes: 1 addition & 1 deletion bl_ui_textbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

# --- ### Change log

# v1.0.2 (09.30.21) - by Marcelo M. Marques
# v1.0.2 (10.31.2021) - by Marcelo M. Marques
# Added: Logic to change state during a mouse move action so that the textbox background color is correctly set

# v1.0.1 (09.20.2021) - by Marcelo M. Marques
Expand Down
2 changes: 1 addition & 1 deletion bl_ui_up_down.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

# --- ### Change log

# (09.30.2021) - by Marcelo M. Marques
# (10.31.2021) - by Marcelo M. Marques
# Added: License, header and warning message.

### \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ ###
Expand Down
4 changes: 2 additions & 2 deletions bl_ui_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@

# --- ### Change log

# v1.0.2 (09.30.2021) - by Marcelo M. Marques
# v1.0.2 (10.31.2021) - by Marcelo M. Marques
# Added: 'valid_modes' property to indicate the 'bpy.context.mode' valid values for displaying the panel.
# Added: 'init_mode' function to allow the 'bl_ui_slider' subclass to call it without triggering an update from the former 'init' function.
# Chang: How we determine whether the user has moved out of the valid area/region, now using the 'valid_display_mode()' function.
# Chang: 'get_area_height' and 'get_area_width' functions to retrieve the values from the area returned by 'get_3d_area_and_region()'.
# Chang: 'handle_event' function to rely on area and region values retrieved by 'get_3d_area_and_region()'. Also replaced the event's
# mouse_region_x|y by calculated values using mouse_x|y and region.x|y because the former mouse_region_x|y stopped working
# after the change on 'bl_ui_draw_op.invoke' method which switches the workspace back and forth.
# Chang: improved reliability on 'timer_event', 'mouse_down', 'mouse_move', 'mouse_up', 'mouse_enter' and 'mouse_exit' overridable
# Chang: improved reliability on 'timer_event', 'mouse_down', 'mouse_move', 'mouse_up', 'mouse_enter' and 'mouse_exit' overridable
# functions by conditioning the returned value

# v1.0.1 (09.20.2021) - by Marcelo M. Marques
Expand Down
7 changes: 1 addition & 6 deletions demo_panel_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

# --- ### Change log

# v1.0.2 (09.30.2021) - by Marcelo M. Marques
# v1.0.2 (10.31.2021) - by Marcelo M. Marques
# Added: 'valid_modes' property to indicate the 'bpy.context.mode' valid values for displaying the panel.
# Added: 'suppress_rendering' function that can be optionally used to control render bypass of the panel widget.
# Added: 'area' and 'region' input parameters to the overridable 'terminate_execution()' function.
Expand Down Expand Up @@ -362,11 +362,6 @@ def suppress_rendering(self, area, region):
If not included here the function in the superclass just returns 'False' and rendering is always executed.
When 'True" is returned below, the rendering of the entire panel is bypassed and it is not drawn on screen.
'''
if bpy.context.region.as_pointer() != self.get_region_pointer():
# Avoid drawing the remote panel simultaneously in every duplicated area.
# The self.get_region_pointer() returns the 'region.as_pointer' value that was saved in the class variable
# when operator was initially invoked (in the case of this demo it will correspond to the N-Panel's region).
return True
return False

def terminate_execution(self, area, region):
Expand Down
3 changes: 1 addition & 2 deletions prefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

# --- ### Change log

# v1.0.2 (09.30.2021) - by Marcelo M. Marques
# v1.0.2 (10.31.2021) - by Marcelo M. Marques
# Chang: the logic that retrieves region.width of the 3d view screen which has the Remote Control

# v1.0.1 (09.20.2021) - by Marcelo M. Marques
Expand Down Expand Up @@ -194,7 +194,6 @@ def execute(self, context):
panX = 100 # Panel X coordinate, for top-left corner (some default, case it fails below)
panY = panH + 40 - 1 # Panel Y coordinate, for top-left corner

# Here the region is used instead of area because data is retrieved from bpy.data.screens['Layout']
region = get_3d_area_and_region(prefs=True)[1]
if region:
if bpy.context.preferences.addons[__package__].preferences.RC_UI_BIND:
Expand Down

0 comments on commit 49ca3fb

Please sign in to comment.