CG · Python · Softimage

Making your PPG pretty – Part 02

In XSI PPGs it is not possible to change the look of the text that appears as labels for parameters. But we have a workaround. We can not only change the font, its size but we can also the color of the foreground and background. To achieve this we have to use the text editor widget.

Adding Text Editor Widget to your PPG

Below is the python code which produces a Demo PPG. Please note that foreground and background color attributes require a hex color code. You can convert the color code from RGB (0 – 255) to hex color code through a number of websites. Here is a link. But doing some pretty basic math, you can create your own hex code. In the python example, I have written two functions to do exactly that. Please go through the code. Also, note that I don’t like using the PPG logic passed on as a string. But for Demo Purpose I am setting the PPG Logic through a string. In your plugins, you have to simply set the logic attribute of your PPG to the plugin file itself. You can find more information regarding this on a nice post written by Andy Nicholas.

Just run this code in XSI and you will get the PPG as shown above. The buttons Change FG and Change BG simply changes some default colors. While selecting the color from the color widgets will also update the foreground and background colors. I have just added three font types to play around with. You can set this to any standard font as you like. As explained in the last post Making Your PPG pretty – Part 1, the trick to make the background transparent is the same. You just set the background color to XSI default gray color. And yes you can be creative here as well. You can use webdings or wingdings font type to get some graphics instead of fonts.

 

from win32com.client import constants as c

DEFAULT_BG_COLOUR = 0xA6A8AB # PPG Gray
DEFUALT_FG_COLOUR = 0x000000 # Black

def defineProp(inProp):
    dispText = inProp.AddParameter3('dispText', c.siString, 'My Text')
    dispText.ReadOnly = True

    inProp.AddParameter3('inText', c.siString, 'My Text')

    inProp.AddParameter3('bgColourInt', c.siInt2, 4)

    inProp.AddParameter3('fgColourInt', c.siInt2, 0)

    inProp.AddParameter3('font', c.siString, 'Arial Black')

    inProp.AddParameter3('rFg', c.siDouble, 0.000)
    inProp.AddParameter3('gFg', c.siDouble, 0.000)
    inProp.AddParameter3('bFg', c.siDouble, 0.000)

    inProp.AddParameter3('rBg', c.siDouble, 0.671)
    inProp.AddParameter3('gBg', c.siDouble, 0.659)
    inProp.AddParameter3('bBg', c.siDouble, 0.651)

    return prop

def definePropLayout(inProp):
    layout = inProp.PPGLayout
    layout.Language = 'Python'

    layout.AddSpacer(0, 20)

    layout.AddGroup('Text')
    dispText = layout.AddItem('dispText', '', c.siControlTextEditor)
    dispText.SetAttribute(c.siUINoLabel,True)
    dispText.SetAttribute(c.siUIFont, 'Arial Black')
    dispText.SetAttribute(c.siUIFontSize, 15)
    dispText.SetAttribute(c.siUIBackgroundColor, DEFAULT_BG_COLOUR)
    dispText.SetAttribute(c.siUIForegroundColor, DEFUALT_FG_COLOUR)
    dispText.SetAttribute(c.siUIHorizontalScroll, False)
    dispText.SetAttribute(c.siUIVerticalScroll, False)
    dispText.SetAttribute(c.siUIVerticalScroll, False)
    dispText.SetAttribute(c.siUIHeight, 45)
    dispText.SetAttribute(c.siUIMarginWidth,5)

    layout.EndGroup()

    layout.AddSpacer(0, 20)

    layout.AddGroup('Text Attributes')
    layout.AddSpacer(0, 20)

    layout.AddItem( 'inText', 'Enter Text', c.siControlString)

    fontList = ['Arial Black', 'Arial Black',
                'Times New Roman', 'Times New Roman',
                'Comic Sans', 'Comic Sans']
    layout.AddEnumControl('font', fontList, 'Select Font')

    layout.AddSpacer(0, 20)

    layout.EndGroup() 

    layout.AddSpacer(0, 40)

    layout.AddRow()
    btnChangeFG = layout.AddButton('changeFG', 'Change FG')
    btnChangeFG.SetAttribute(c.siUICX, 150)
    btnChangeFG.SetAttribute(c.siUICY, 50)

    btnChangeBG = layout.AddButton('changeBG', 'Change BG')
    btnChangeBG.SetAttribute(c.siUICX, 150)
    btnChangeBG.SetAttribute(c.siUICY, 50)

    btnSetDefaultColours = layout.AddButton('setDefault', 'Set Defaults')
    btnSetDefaultColours.SetAttribute(c.siUICX, 150)
    btnSetDefaultColours.SetAttribute(c.siUICY, 50)

    layout.EndRow()

    layout.AddSpacer(0, 40)

    layout.AddColor('rFg', 'FG Color')

    layout.AddColor('rBg', 'BG Color')

    logicStr = """
from win32com.client import constants as c

def changeFG_OnClicked():
    prop = PPG.Inspected(0)
    layout = PPG.PPGLayout

    currentFGColourIndex = prop.fgColourInt.value
    currentBGColourIndex = prop.bgColourInt.value

    colourIndex = currentFGColourIndex + 1

    if colourIndex == currentBGColourIndex or colourIndex > 4:
        colourIndex += 1
        if colourIndex > 4:
            colourIndex = 0
            if colourIndex ==  currentBGColourIndex:
                colourIndex += 1

    colours = [0x000000, 0xB5F669, 0x149FF0, 0x8069F6, 0xA6A8AB]
    colour = colours[colourIndex]
    dispText = layout.Item('dispText')
    dispText.SetAttribute(c.siUIForegroundColor, colour)

    prop.fgColourInt.value = colourIndex

    PPG.Refresh()

    return

def changeBG_OnClicked():
    prop = PPG.Inspected(0)
    layout = PPG.PPGLayout

    currentFGColourIndex = prop.fgColourInt.value
    currentBGColourIndex = prop.bgColourInt.value

    colourIndex = currentBGColourIndex + 1

    if colourIndex == currentFGColourIndex or colourIndex > 4:
        colourIndex += 1
        if colourIndex > 4:
            colourIndex = 0
            if colourIndex ==  currentFGColourIndex:
                colourIndex += 1

    colours = [0x000000, 0xB5F669, 0x149FF0, 0x8069F6, 0xA6A8AB]
    colour = colours[colourIndex]
    dispText = layout.Item('dispText')
    dispText.SetAttribute(c.siUIBackgroundColor, colour)

    prop.bgColourInt.value = colourIndex

    PPG.Refresh()

    return

def inText_OnChanged():
    prop = PPG.Inspected(0)
    prop.dispText.Value = str(prop.inText.Value)
    PPG.Refresh()

    return

def font_OnChanged():
    prop = PPG.Inspected(0)
    layout = PPG.PPGLayout

    dispText = layout.Item('dispText')
    dispText.SetAttribute(c.siUIFont, prop.font.Value)
    PPG.Refresh()

    return

def setDefault_OnClicked():
    layout = PPG.PPGLayout
    prop = PPG.Inspected(0)

    prop.dispText.Value = 'My Text'
    prop.inText.Value = 'My Text'

    prop.rFg.Value = 0.0
    prop.gFg.Value = 0.0
    prop.bFg.Value = 0.0    

    prop.rBg.Value = 0.671
    prop.gBg.Value = 0.659
    prop.bBg.Value = 0.651

    dispText = layout.Item('dispText')
    dispText.SetAttribute(c.siUIBackgroundColor, 0xA6A8AB)
    dispText.SetAttribute(c.siUIForegroundColor, 0x000000)
    dispText.SetAttribute(c.siUIFont, 'Arial Black')

    prop.fgColourInt.Value = 0
    prop.bgColourInt.Value = 4

    PPG.Refresh()

def rFg_OnChanged():
    _updateColour(1)
    return

def gFg_OnChanged():
    _updateColour(1)
    return

def bFg_OnChanged():
    _updateColour(1)

    return

def rBg_OnChanged():
    _updateColour(0)
    return

def gBg_OnChanged():
    _updateColour(0)
    return

def bBg_OnChanged():
    _updateColour(0)

    return

def _updateColour(fg):
    prop = PPG.Inspected(0)

    if fg:
        r = prop.rFg.Value
        g = prop.gFg.Value
        b = prop.bFg.Value
    else:
        r = prop.rBg.Value
        g = prop.gBg.Value
        b = prop.bBg.Value    

    r, g, b = denormalizeRGB(r, g, b)

    hex = rgbToHex(r, g, b)

    layout = PPG.PPGLayout
    dispText = layout.Item('dispText')

    if fg:
        dispText.SetAttribute(c.siUIForegroundColor, hex)
    else:
        dispText.SetAttribute(c.siUIBackgroundColor, hex)

    PPG.Refresh()

    return

def denormalizeRGB(r, g, b):
    r = int(round(r * 255, 0))
    g = int(round(g * 255, 0))
    b = int(round(b * 255, 0))

    return r, g, b

def rgbToHex(r, g, b):
    hexString = '0123456789ABCDEF'
    remR = r % 16
    divR = r / 16
    rHex = '%s%s'%(hexString[divR], hexString[remR])

    remG = g % 16
    divG = g / 16
    gHex = '%s%s'%(hexString[divG], hexString[remG])

    remB = b % 16
    divB = b / 16
    bHex = '%s%s'%(hexString[divB], hexString[remB])

    hex = eval('0x%s%s%s'%(bHex, gHex, rHex))

    return hex

"""

    layout.Logic = logicStr

    return prop

prop = XSIFactory.CreateObject('CustomProperty')
prop.Name = 'myProp'
prop = defineProp(prop)
prop = definePropLayout(prop)
Application.InspectObj(prop, '', 'MyProperty')
CG · Python · Softimage

Making your PPG pretty – Part 01

PPG’s provide GUI for users to interact with your plugins/tools/script. They are a mini-application, if you may. So why not make your mini-application look cool. Here is how you can make your PPG prettier.

Adding Images/Logos to your PPG

You can change this boring PPG,

scrNoLogo1

to this,

scrAllLogo1

 

Please note that you can add only .bmp formats. So how do we get the transparency with .bmp? hmmm, elementary my dear Watson. The trick is to use the background color of image file same as that of your PPG.

 

To do that open Softimage and take a capture the screen. In Photoshop or any other image-editing software bring in the capture and set the bg color to the Softimage application window color from the capture.

bgColorImage

Remember, the color varies from monitor to monitor and profile to profile. So to make sure this works on all the calibrations, use the same monitor and color profile from which you capture and make your logo.

 

Just clean your image off any background and use the background created from the capture.

imageClean1

Save your image as .bmp and you are done.

cleanedLogo.jpg

You can add company/studio logo to the PPG,  image files as bullets for parameters, signature etc., the possibilities are endless.

 

You can set images to your PPG  by using the c.siControlBitmap item type. All it needs is a path to a .bmp file. Here’s equivalent python code.

 

 

from win32com.client import constants as c

LOGO_PATH = r'---path to your .bmp file here---'

def defineProp(inProp):
 inProp.AddParameter3('logo', c.siString)
 inProp.AddParameter3('myParam', c.siDouble)
 inProp.AddParameter3('anotherParam', c.siBool)

 return prop

def definePropLayout(inProp):
 layout = inProp.PPGLayout
 logo = layout.AddItem('logo','',c.siControlBitmap)
 logo.SetAttribute(c.siUIFilePath,  LOGO_PATH)
 logo.SetAttribute(c.siUINoLabel, True)

 layout.AddSpacer(0, 20)

 layout.AddGroup('My Parameters')
 layout.AddSpacer(0, 10)
 layout.AddItem('myParam','A Parameter')
 layout.AddSpacer(0, 5)
 layout.AddItem('anotherParam','Another Parameter')
 layout.AddSpacer(0, 5)
 layout.EndGroup()
 layout.AddSpacer(0, 20)

 return prop

prop = XSIFactory.CreateObject('CustomProperty')
prop.Name = 'myProp'
prop = defineProp(prop)
prop = definePropLayout(prop)
Application.InspectObj(prop, '', 'MyProperty', c.siModal, False)