Block Manager - How To Get Viewport "Thumbnail" For Use In UI Elsewhere?

Hello,

I’ve been scouring the docs looking for how to expose this viewport and/or create a new matching viewport and set its properties from a Python 3 Script.

I want to “get” the thumbnail viewport that is generated with each block instance, create a copy of it and set it’s display mode/camera settings, and then use that in a custom grid layout within an Eto.Form

It appears to me this is a viewport control with viewport navigation disabled but is a viewport that you can set the style and camera position of.

I want to mimic this so that I have a “live” thumbnail viewport in each grid cell of each block instance in the model without all the additional block instance information/settings shown in the block manager.

Below you can see the labels of my UI cell layout, each cell would get an ImageView control of the block instance viewport. I have all this covered but cannot seem to find where or how to access the viewport thumbnail of the block instance being created in the Block Manager

Here is my code thus far:

#! python 3
import Rhino
import Eto.Forms as forms
import Eto.Drawing as drawing

# Script Level Variables
dark_mode = Rhino.Runtime.HostUtils.RunningInDarkMode  # Get Current Rhino Theme For Custom Dark Mode UI Functions On Script Initialization

bg_color_light = drawing.Color(10, 10, 10)
bg_color_dark = drawing.Color(220, 220, 220)

mg_color_light = drawing.Color(1, 1, 1)
mg_color_dark = drawing.Color(240, 240, 240)

fg_color_light = drawing.Color(1, 1, 1)
fg_color_dark = drawing.Color(180, 180, 180)

b_color_light = drawing.Color(40, 40, 40)
b_color_dark = drawing.Color(240, 240, 240)

s_color_light = drawing.Colors.LightGrey  # Shadow Color To Replace Color Highlight When In Light Mode
s_color_dark = drawing.Color(240, 240, 240)

e_color_light = drawing.Color(20, 20, 20)
e_color_dark = drawing.Color(250, 250, 250)

d_color_light = fg_color_light
d_color_dark = drawing.Color(210, 210, 210)

t_color_dark = fg_color_light
t_color_light = fg_color_dark

shadow_height = 20

library_height = 200  # The Distance The Dynamic UI Tray "Travels" When Hidden/Shown
padding = 30
lib_padding = padding + 20
thumbnail_padding = 5
radius = 20

show_block_library = True  # Default Show Tray State

# Initialize width and height variables
w = 0
h = 0

s = Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.Size
w = s.Width
h = s.Height

class BlockLibrary(forms.Form):
    def __init__(self):
        super().__init__()

        global block_library_instance
        block_library_instance = self  # Storing reference to MainToolbar instance

        # Set Form General Settings
        self.Title = "Block Library"
        self.Size = drawing.Size(1000, 500)  # Set The Overall Form Size
        self.WindowStyle = forms.WindowStyle.NONE
        self.Resizable = False
        self.MovableByWindowBackground = True

        # Add Transparent Style To The Form Background Panel
        self.Styles.Add[forms.Panel]("transparent", self.MyFormStyler)
        self.Style = "transparent"

        self.CreateUI()

    def CreateUI(self):
        # Rhino.RhinoApp.WriteLine("create UI call")

        # Add Items To Layout
        self.layout = forms.PixelLayout()

        # Setup bitmap to have background graphics drawn on
        pixelformat = drawing.PixelFormat.Format32bppRgba
        bitmap = drawing.Bitmap(self.Size, pixelformat)
        self.graphics = drawing.Graphics(bitmap)

        self.bl_graphics = forms.ImageView()
        self.bl_graphics.Image = bitmap

        # Add Graphics
        self.layout.Add(self.bl_graphics, 0, 0)

        self.DrawBlockLibraryGraphics(show_block_library)  # Call The Function That Creates The Graphics

        # Calculate grid cell count
        cell_size = 150  # Set your desired cell size here
        column_count, row_count = self.calculate_grid(cell_size)

        top_padding = 30

        # Add text labels to the grid layout
        for row in range(row_count):
            for col in range(column_count):
                # thumbnail = forms.ImageView()
                label = forms.Label()
                label.Text = f"({row}, {col})"
                label.TextColor = b_color_light if dark_mode else b_color_dark
                self.layout.Add(label, (col * cell_size) + lib_padding, (row * cell_size) + lib_padding + top_padding)

        self.Content = self.layout

    def DrawBlockLibraryGraphics(self, show_block_library):

        # Create The Background Graphics For The Main Toolbar
        bg_color = bg_color_dark if dark_mode else bg_color_light
        # Create Background Main Toolbar Graphics
        brush_1 = drawing.SolidBrush(bg_color)
        rect_1 = drawing.Rectangle(padding, padding, self.Width - padding * 2, self.Height - padding * 2)
        path_1 = drawing.GraphicsPath.GetRoundRect(rect_1, radius, radius, radius, radius)

        # Draw Background Main Toolbar Graphics
        self.graphics.FillPath(brush_1, path_1)

        self.graphics.Dispose()

    # Handle Overall Background Transparency
    def MyFormStyler(self, control):
        self.BackgroundColor = drawing.Colors.Transparent
        window = control.ControlObject
        if hasattr(window, "AllowsTransparency"):
            window.AllowsTransparency = True
        if hasattr(window, "Background"):
            brush = window.Background.Clone()
            brush.Opacity = 0
            window.Background = brush
        else:
            color = window.BackgroundColor
            window.BackgroundColor = color.FromRgba(0, 0, 0, 0)

    # Calculate Cell Size For Custom Grid Layout
    def calculate_grid(self, cell_size):
        # Calculate grid column count
        column_count = int((self.Size.Width - (lib_padding * 2)) / cell_size)

        # Calculate grid row count
        row_count = int((self.Size.Height - (lib_padding * 2)) / cell_size)

        return column_count, row_count


def EstablishForm():
    block_library = BlockLibrary()
    block_library.Location = drawing.Point(w / 2 - block_library.Width / 2, block_library.Height)
    block_library.Owner = Rhino.UI.RhinoEtoApp.MainWindow
    block_library.Show()


if __name__ == "__main__":
    EstablishForm()

Thank you for your help!

Hi @michaelvollrath,

Does InstanceDefinition.CreatePreviewBitmap help?

– Dale

2 Likes

Yes, that appears to be what I am after! Thank you @dale ! :pray:

Hi @dale ,

Are these the only display mode preview settings available for the block instance thumbnail?

image

I would like to use a user created display mode like “My Display Mode” that may have specific display mode settings not covered by the standard “Default, Rendered, Shaded, Wireframe” as I don’t believe these offer the best “universal legibility” for varying block instances.

I tried to create a new display mode or get an existing display mode by name but I’m having difficulty using it for the instance object preview:

        block_dm = Rhino.DocObjects.DisplayMode.RenderPreview

        test_dm_guid = Rhino.Display.DisplayModeDescription.AddDisplayMode("My Test Displaymode")
        Rhino.RhinoApp.WriteLine(str(test_dm))

Code below using “rendered” display mode for instance object preview:

        block_dm = Rhino.DocObjects.DisplayMode.RenderPreview

        for block in block_table:
            block_names.append(block.Name)  # Get Individual Block Name
            block_thumbnails.append(Rhino.DocObjects.InstanceDefinition.CreatePreviewBitmap(block, Rhino.Display.DefinedViewportProjection.Perspective, block_dm, t_size))  # Create Bitmap Of Block Preview Image
        Rhino.RhinoApp.WriteLine(str(block_names))

What the “rendered” display mode currently looks like (I realize I can change this in document properties)

image

And an example of a user defined Display Mode I would like to use as the instance object thumbnail display mode:
image

Thanks for your help!

I’ll see what I can do.

https://mcneel.myjetbrains.com/youtrack/issue/RH-81970

– Dale

2 Likes

Thank you @dale , I appreciate you!

Following this thread with interest,
Could be a great way of acheiving the goal of this thread

Would we be able to have a custom display conduit in there?

Hi @david.birch.uk,

No, just a custom display mode.

– Dale