2
$\begingroup$

I'm new to Python

I would like to display in the 3D viewport a better representation of the Xray mode. The header icon is not visible enough to me. Not always easy to see the difference between ON and OFF.

I have search for a potential addon or script without success.

enter image description here

$\endgroup$
5
  • 1
    $\begingroup$ Hello :). Does this help? How to edit 2.8 UI icons? $\endgroup$ – Jachym Michal Oct 10 '20 at 15:05
  • $\begingroup$ Hi and thanks for your answer but I don't see how it can help for my question $\endgroup$ – Stefakapapy Oct 11 '20 at 1:42
  • $\begingroup$ Hey :). I thought you wanted to change the header icon, to 'better represent the X-Ray mode', right? If not, please make your question more clear. $\endgroup$ – Jachym Michal Oct 11 '20 at 5:51
  • 1
    $\begingroup$ Hi. Sorry I tought the screenshot was pretty clear. In fact I would like to have a bar at the bottom as you can see $\endgroup$ – Stefakapapy Oct 11 '20 at 11:20
  • $\begingroup$ It was clear enough, i just missed it :). $\endgroup$ – Jachym Michal Oct 11 '20 at 11:37
3
$\begingroup$

enter image description here

Make some visual overlay

Could not help but see the link between this and Bug in addon to Change header color dynamically The addon there was to remind user they are in automatic keyframe mode.

Remember at the time thinking would make an interesting addon if given a generic way to link a property toggle with toggling a setting. However have not returned until now

Similarly an edit to change the behaviour to instead change the bg color of the 3d view if in xray mode.

Consider this a "proof of concept" test script, a more subtle indicator could be used.

paste into text editor click run script.

import blf
import bpy

bl_info = {
    "name": "New Object",
    "author": "Your Name Here",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "View3D > Add > Mesh > New Object",
    "description": "Adds a new Mesh Object",
    "warning": "",
    "wiki_url": "",
    "category": "Add Mesh",
}

highlight_color = (0.4, 0, 0)

class DrawingClass:
    def __init__(self, prop):
        from bpy import context
        self.prop = prop
        self.col = context.preferences.themes[0].view_3d.space.gradients.high_gradient[:] 
        self.handle = bpy.types.SpaceView3D.draw_handler_add(
            self.draw_text_callback, (), 'WINDOW', 'POST_PIXEL')

    def draw_text_callback(self):
        from bpy import context
        font_id = 0  # XXX, need to find out how best to get this.
        if not hasattr(context, "scene"):
            return None
        shading = context.space_data.shading
        if shading.show_xray:
            context.preferences.themes[0].view_3d.space.gradients.high_gradient = highlight_color
            # draw some text
            blf.position(font_id, 18, 50, 0)
            blf.size(font_id, 50, 72)
            blf.draw(font_id, f"{self.prop}")

        else:
            context.preferences.themes[0].view_3d.space.gradients.high_gradient = self.col

    def remove_handle(self):
        from bpy import context
        context.preferences.themes[0].view_3d.space.gradients.high_gradient = self.col
        bpy.types.SpaceView3D.draw_handler_remove(self.handle, 'WINDOW')


dc = None


def register():
    global dc
    dc = DrawingClass("XRay Mode")

def unregister():
    global dc
    if dc:
        dc.remove_handle()
        dc = None

if __name__ == "__main__":
    register()

Leads to more questions.

An issue could be since a draw handler is defined for type, could be an issue with syncing when more than 1 view 3d is being drawn on the screen. Also setting the theme bg color of the viewport is blend file wide.

enter image description here

A quick test confirmed my fears. Notice the text is correct but the theme bg color is not.

What is interesting is having what is like two themes active at once

$\endgroup$
4
  • 1
    $\begingroup$ Amazing, exactly what I was looking for, thanks a million times $\endgroup$ – Stefakapapy Oct 11 '20 at 11:25
  • $\begingroup$ Is there a way to center this "XRay Mode" text on the screen and when the screen is resized ? $\endgroup$ – Stefakapapy Oct 11 '20 at 12:40
  • $\begingroup$ blender.stackexchange.com/a/107646/15543 $\endgroup$ – batFINGER Oct 11 '20 at 12:42
  • $\begingroup$ Thanks again, I will work on all of your informations you gave me $\endgroup$ – Stefakapapy Oct 11 '20 at 13:32
1
$\begingroup$

Here is the final script if anyone is interested ;)

import blf
import bpy

bl_info = {
    "name": "Better Xray Visualization",
    "author": "Stefakapapy",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "Toggle Xray",
    "description": "Displays better visual representation on screen",
    "category": "Interface",
}

class DrawingClass:
    def __init__(self, prop):
        from bpy import context
        
        self.prop = prop
        self.handle = bpy.types.SpaceView3D.draw_handler_add(
            self.draw_text_callback, (), 'WINDOW', 'POST_PIXEL')
            
    def draw_text_callback(self):
        from bpy import context
        
        if not hasattr(context, "scene"):
            return None

        shading = context.space_data.shading
        shading_type = context.space_data.shading.type
        xray = shading.show_xray
        xray_wireframe = shading.show_xray_wireframe
        
        if (shading_type=="SOLID" and xray) or (shading_type=="WIREFRAME" and xray_wireframe):
            display_xray = True
        else:
            display_xray = False

        if display_xray:
                font_id = 0  # XXX, need to find out how best to get this.
                color1 = (0, 0.624, 1.0, 1.0)
                width = context.area.width
                
                blf.size(font_id, 40, 72)
                dim_x = blf.dimensions(font_id, self.prop)[0]/2
                blf.position(font_id, width/2-dim_x, 18, 0)
                blf.color(font_id, *color1)
                blf.draw(font_id, f"{self.prop}")

    def remove_handle(self):
        from bpy import context
        bpy.types.SpaceView3D.draw_handler_remove(self.handle, 'WINDOW')


dc = None


def register():
    global dc
    dc = DrawingClass("XRay Mode")

def unregister():
    global dc
    if dc:
        dc.remove_handle()
        dc = None

if __name__ == "__main__":
    register()
$\endgroup$
1
  • $\begingroup$ Good one. For future ref, can simply edit your previous answer. At a certain rep deleted answers are visible. This post is hidden. It was deleted 55 mins ago by the post author. $\endgroup$ – batFINGER Oct 14 '20 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.