7
$\begingroup$

I'm trying to change ui colors from within (blender's) console.

I'll admit it's a peculiar idea (common sense suggest to import the "xml") but I want to propose 3 or 4 "color hacks" for blender's default color theme, its the sort of change every pro would suggest at first moments notice (its not supposed to be a redesign or revamp).

But how to rise to attention at "blendernation"? By posting an unreachable xml at "blenderartists"?

Instead of downloading, saving, unwrapping and installing a file my "color hack" could simply be pasted into the console and previewed in a nondestructive manner (blender discard unsaved ui changes when it quits) -- ie it'll help my "color hack" to rise to attention of blender's Bartholomew.

Thanks in advance.

Curious how the fixes look like, or what is it good for? Its all about the "setting buttons", here the user can distinguish between a "function" and a "setting" button. Quickfixes

$\endgroup$

3 Answers 3

4
$\begingroup$

Here's an example script:

import bpy

ui = bpy.context.user_preferences.themes[0].user_interface

#>>> C.user_preferences.themes[0].user_interface.wcol_radio.inner[:]
wcol_radio_inner = (0.275, 0.275, 0.275, 1.0)

#>>> C.user_preferences.themes[0].user_interface.wcol_radio.inner_sel[:]
wcol_radio_inner_sel = (0.33, 0.5, 0.76, 1.0)

#>>> C.user_preferences.themes[0].user_interface.wcol_radio.show_shaded
wcol_radio_show_shaded = True

#>>> C.user_preferences.themes[0].user_interface.wcol_radio.shadetop
wcol_radio_shadetop = 15

#>>> C.user_preferences.themes[0].user_interface.wcol_radio.shadedown
wcol_radio_shadedown = -15

#>>> C.user_preferences.themes[0].user_interface.wcol_radio.text
wcol_radio_text = (1, 1, 1)


ui.wcol_regular.inner = wcol_radio_inner
ui.wcol_regular.inner_sel = wcol_radio_inner_sel
ui.wcol_regular.show_shaded = wcol_radio_show_shaded
ui.wcol_regular.shadetop = wcol_radio_shadetop
ui.wcol_regular.shadedown = wcol_radio_shadedown
ui.wcol_regular.text = wcol_radio_text

ui.wcol_toggle.inner = wcol_radio_inner
ui.wcol_toggle.inner_sel = wcol_radio_inner_sel
ui.wcol_toggle.show_shaded = wcol_radio_show_shaded
ui.wcol_toggle.shadetop = wcol_radio_shadetop
ui.wcol_toggle.shadedown = wcol_radio_shadedown
ui.wcol_toggle.text = wcol_radio_text

Note that you need to run this from the text editor, this wouldn't really work as addon - at the time of registration, we are not allowed to access the context.

BTW, with the above theme, the toggle buttons in the text editor sidebar for wrapping etc. look really odd.

Looking at the 2.69 testbuild 1, the transform manipulators in the View3D header appear like props:

2.69 testbuild1 View3D Header

But it's odd that the enable/disable button draws not the same. For selection mode, it's arguable whether this should look like a property set, as it actually changes something (mesh selection, e.g. verts+edges selected, go to face mode, nothing selected).

$\endgroup$
3
  • $\begingroup$ Nooo he didnt like my "color hack" T_T how depressing. Just kidding just kidding, thanks for the answer ^_^ $\endgroup$
    – akikun
    Oct 3, 2013 at 18:53
  • $\begingroup$ The "color hacks" affect a butch of "setting" and or "toggle" buttons... also the "pressed" buttons need to be colored with the default "blueish" color (of blender's "radio buttons"). The great advantage of my "hack" is that it becomes clear whether or not something is a "toggle" or a "action". $\endgroup$
    – akikun
    Oct 3, 2013 at 19:17
  • $\begingroup$ Note that in the new version (now=2.93), user_preferences have to be preferences instead. Related references : docs.blender.org/api/current/bpy.types.Preferences.html and docs.blender.org/api/current/bpy.types.ThemeUserInterface.html . $\endgroup$ Nov 29, 2021 at 3:52
2
$\begingroup$

For themable things in editors use:
bpy.context.user_preferences.themes[0].<editor>.<thing> = <color>

The python console has completion to help with the names of things.

The 3D view is also an editor, the following example sets lamps to white: bpy.context.user_preferences.themes[0].view_3d.lamp = (1,1,1)

$\endgroup$
0
$\begingroup$

Is this CoDEmanX's snippet "bpy.context.user_preferences.themes[0].user_interface" put to work... or what I wanted to ask? I wont mind if my answer gets delete but this worked for me:

def scriptrunner():
    global gui
    global Bucket
    global Spray
    global getPresets

    # swatch: Standard (unchanged) colors of blenders ui
    # alias: A batch of solid colors
    # snuff: Some tryout colors
    # 
    swatch, solid, snuff = getPresets()

    # Blenders standard widgets
    # 
    print(dir(gui))

    # Changes for the glowing "Checkboxes"
    # ("unglow" can be removed to keep the default)
    # 
    unglow = Bucket()
    unglow.text = solid.black
    unglow.text_sel = solid.black
    unglow.apply(gui, 'wcol_option')

    # Changes for the "Slider widget"
    # ("brighten" can be deleted to keep the default)
    # 
    brighten = Bucket()
    brighten.inner = (0.600, 0.600, 0.600, 1.0)
    brighten.inner_sel = (0.580, 0.580, 0.580, 1.0)
    brighten.item = (0.671, 0.671, 0.671, 1.0)
    brighten.shadedown = 4
    brighten.shadetop = -24
    brighten.show_shaded = True
    brighten.apply(gui, 'wcol_numslider')

    # Changes for the commands aka "Tool widget"
    # 
    defocus = Bucket()
    defocus.outline = (0.404, 0.404, 0.404)
    defocus.inner = (0.518, 0.518, 0.518, 1.0)
    defocus.inner_sel = (0.392, 0.392, 0.392, 1.0)
    defocus.item = (0.098, 0.098, 0.098, 1.0)
    defocus.shadedown = -5
    defocus.shadetop = 10
    defocus.show_shaded = True
    defocus.apply(gui, 'wcol_tool')

    # Over paints the "Frames of sadness"
    # 
    allUnframed = Spray([
        'wcol_num', 
        'wcol_numslider', 
        'wcol_text', ])

    for i, q in allUnframed:
        allUnframed[i].outline = (0.380, 0.380, 0.380)
        allUnframed[i].apply(gui, q)

    # It'll "bind" the colors of the "Toggle buttons"
    # 
    allBindings = Spray([
        'wcol_menu', 
        'wcol_option', 
        'wcol_radio', 
        'wcol_regular', 
        'wcol_toggle', ])

    for i, q in allBindings:
        allBindings[i].inner = swatch.charcoal
        allBindings[i].inner_sel = swatch.skyblue
        allBindings[i].apply(gui, q)

    # Additional tweaks to the previous "Toggle buttons"
    # 
    allUnframed = Spray([
        'wcol_menu', 
        'wcol_option', 
        'wcol_radio', 
        'wcol_regular', 
        'wcol_toggle', ])

    for i, q in allUnframed:
        allUnframed[i].outline = (0.200, 0.200, 0.200)
        allUnframed[i].apply(gui, q)

    # Brightens some text fonts
    # ("allBindings" created dark "text" on dark "buttons")
    # 
    allAdjusted = Spray([
        'wcol_regular', 
        'wcol_toggle', ])

    for i, q in allAdjusted:
        allAdjusted[i].text = (0.900, 0.900, 0.900)
        allAdjusted[i].text_sel = solid.black
        allAdjusted[i].show_shaded = True  #its OFF by default...
        allAdjusted[i].shadedown = -15
        allAdjusted[i].shadetop = 15
        allAdjusted[i].apply(gui, q)







    return True

def getPresets():
    global Presetfactory
    swatch = Presetfactory()
    solid = Presetfactory()
    snuff = Presetfactory()

    # skyblue: The color of "Inner Selected" of "Radio Widgets"
    # charcoal: The ubiquitos charcoal for toggles and switches
    # 
    @swatch
    def skyblue(): 
        return (0.337, 0.502, 0.761, 1.0)
    @swatch
    def charcoal(): 
        return (0.275, 0.275, 0.275, 1.0)

    # A batch of opaque (or solid) colors.
    # 
    @solid
    def black(): 
        return (0.000, 0.000, 0.000)
    @solid
    def white():
        return (1.000, 1.000, 1.000)

    # A batch of tryout colors
    # 
    @snuff
    def white():
        return (1.000, 1.000, 1.000, 1.0)
    @snuff
    def red():
        return (0.900, 0.010, 0.010, 1.0)
    @snuff
    def yellow():
        return (1.000, 1.000, 0.000, 1.0)

    return swatch, solid, snuff

# (All "buckets" and "sprays" are interfaces...
#  ...only "fill()" gets to see "gui")
#
class Bucket():
    def __init__(self):
        self.scriptwork = {
            'text': None, 
            'text_sel': None, 
            'inner': None, 
            'inner_sel': None, 
            'item': None, 
            'outline': None, 
            'shadedown': None, 
            'shadetop': None, 
            'show_shaded': None, }

    def apply(self, gui, firstname):
        # 
        # Pythons "setattr()" accesses blenders:
        # >> gui.<button>.<setting> = <color>

        knockout = self.scriptwork
        for q in knockout.keys():
            if knockout[q] != None:
                setattr(
                    getattr(gui, firstname), q, knockout[q] )

        # Prevents multiple reruns
        # (the pending changes were already applied)
        # 
        for q in knockout.keys():
            knockout[q] = None

    def __getattr__(self, label):
        return self.scriptwork[label]

    def __setattr__(self, label, contents):
        if label != 'scriptwork':
            if label not in self.__dict__['scriptwork'].keys():
                print("Attention, unkown gui property:", label)
                print("Available are:", self.__dict__['scriptwork'].keys())
        if label == 'scriptwork':
            self.__dict__['scriptwork'] = contents
            return None
        self.__dict__['scriptwork'][label] = contents
        return None
    pass

class Spray():
    def __init__(self, dispatch):
        global Bucket
        self.scriptwork = {
            'bucketnames': dispatch, 
            'buckets': [Bucket() for q in dispatch ], }

    def __iter__(self):
        for f in range(len(self.scriptwork['bucketnames'])):
            i = 0 + f
            q = '' + self.scriptwork['bucketnames'][f]
            yield i, q

    def __getitem__(self, frame):
        return self.scriptwork['buckets'][frame]
    pass

# (Steals and stores the decorator user)
# 
class Presetfactory():
    def __init__(self):
        self.scriptwork = {}

    def __call__(self, target):
        firstname = '' + target.__name__
        self.scriptwork[firstname] = target
        return "Succeffully collected the preset."

    def __getattr__(self, label):
        return self.scriptwork[label]()
    pass

# (This script accesses blenders's "user_interface")
# 
import bpy
gui = bpy.context.user_preferences.themes[0].user_interface
scriptrunner()
$\endgroup$
2
  • $\begingroup$ I would look into the property system to store variable rather than using globals. - wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/… $\endgroup$
    – neomonkeus
    Oct 5, 2013 at 13:56
  • $\begingroup$ @neomonkeus the script doesn't use "globals" to store values... the script uses the "global" keyword to fetch function and or class definitions. $\endgroup$
    – akikun
    Oct 5, 2013 at 15:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .