"""--------------------------------------------------------------------------------------------
--- fhPatternGadegt
--- 2013 Ferdinand Hoppe
--------------------------------------------------------------------------------------------"""
import math
import c4d
import fhp
from c4d import gui
class fhPatternGadegt(gui.GeUserArea):
"""
A gui gadget to modify and display boolean patterns.
"""
def __init__(self, host):
"""
:param host: The hosting BaseToolData instance
"""
self.Host = host
self.BorderWidth = None
self.CellPerColumn = None
self.CellWidht = fhp.IDC_SELECTLOOP_CELLSIZE[0]
self.CellHeight = fhp.IDC_SELECTLOOP_CELLSIZE[1]
self.Columns = None
self.Height = None
self.Width = None
self.MinHeight = fhp.IDC_SELECTLOOP_GADGET_MINH
self.MinWidht = fhp.IDC_SELECTLOOP_GADGET_MINW
self.MouseX = None
self.MouseY = None
"""--------------------------------------------------------------------------------------------
Overridden methods
-------------------------------------------------------------------------------------------"""
def Init(self):
"""
Init the gadegt.
:return : Bool
"""
self.GetColors()
return True
def GetMinSize(self):
"""
Resize the gadget
:return : int, int
"""
return int(self.MinWidht), int(self.MinHeight)
def Sized(self, w, h):
"""
Get the gadegts height and width
"""
self.Height, self.Width = int(h), int(w)
self.FitGadegt()
def Message(self, msg, result):
"""
Fetch and store mouse over events
:return : bool
"""
if msg.GetId() == c4d.BFM_GETCURSORINFO:
base = self.Local2Screen()
if base:
self.MouseX = msg.GetLong(c4d.BFM_DRAG_SCREENX) - base['x']
self.MouseY = msg.GetLong(c4d.BFM_DRAG_SCREENY) - base['y']
self.Redraw()
self.SetTimer(100)
return gui.GeUserArea.Message(self, msg, result)
def Timer(self, msg):
"""
Timer loop to catch OnMouseExit
"""
base = self.Local2Global()
bc = c4d.BaseContainer()
res = gui.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, bc)
mx = bc.GetLong(c4d.BFM_INPUT_X) - base['x']
my = bc.GetLong(c4d.BFM_INPUT_Y) - base['y']
if res:
if not (mx >= 0 and mx <= self.Width and my >= 0 and my <= self.Height):
self.SetTimer(0)
self.Redraw()
def DrawMsg(self, x1, y1, x2, y2, msg):
"""
Draws the gadget
"""
# double buffering
self.OffScreenOn(x1,y1,x2,y2)
# background & border
self.DrawSetPen(self.ColBackground)
self.DrawRectangle(x1,y1,x2,y2)
if self.BorderWidth:
self.DrawBorder(c4d.BORDER_THIN_IN, x1, y1, self.BorderWidth + 2, y2 - 1)
# draw pattern
for pid, state in self.Host.Pattern:
x, y = self.GetRect(pid)
self.DrawCell(x,y, state, self.IsFocus(x, y))
"""--------------------------------------------------------------------------------------------
Public methods
-------------------------------------------------------------------------------------------"""
def Update(self, cid = None):
"""
Update the gadget.
:param cid: A pattern id to toggle.
"""
if cid and cid < self.Host.PatternSize:
self.Host.Pattern[cid] = not self.Host.Pattern[cid]
self.FitGadegt()
self.Redraw()
"""--------------------------------------------------------------------------------------------
Private methods
-------------------------------------------------------------------------------------------"""
def GetColors(self, force = False):
"""
Set the drawing colors.
:return : Bool
"""
self.ColScale = 1.0 / 255.0
if self.IsEnabled() or force:
self.ColBackground = self.getColorVector(c4d.COLOR_BG)
self.ColCellActive = c4d.GetViewColor(c4d.VIEWCOLOR_ACTIVEPOINT) * 0.9
self.ColCellFocus = self.getColorVector(c4d.COLOR_BGFOCUS)
self.ColCellInactive = self.getColorVector(c4d.COLOR_BGEDIT)
self.ColEdgeDark = self.getColorVector(c4d.COLOR_EDGEDK)
self.ColEdgeLight = self.getColorVector(c4d.COLOR_EDGELT)
else:
self.ColBackground = self.getColorVector(c4d.COLOR_BG)
self.ColCellActive = self.getColorVector(c4d.COLOR_BG)
self.ColCellFocus = self.getColorVector(c4d.COLOR_BG)
self.ColCellInactive = self.getColorVector(c4d.COLOR_BG)
self.ColEdgeDark = self.getColorVector(c4d.COLOR_EDGEDK)
self.ColEdgeLight = self.getColorVector(c4d.COLOR_EDGELT)
return True
def GetCellPen(self, state, isfocus):
"""
Get the color for cell depending on its state.
:param state : The state
:param isfocus : If the cell is hoovered.
:return : c4d.Vector()
"""
if state: pen = self.ColCellActive
else: pen = self.ColCellInactive
if self.IsEnabled() and isfocus:
return (pen + c4d.Vector(2)) * 1/3
else: return pen
def DrawCell(self, x, y, state, isfocus):
"""
Draws a gadget cell.
:param x: local x
:param y: local y
:param state: On/Off
:param isfocus: MouseOver state
"""
# left and top bright border
self.DrawSetPen(self.ColEdgeLight)
self.DrawLine(x , y, x + self.CellWidht , y)
self.DrawLine(x , y, x , y + self.CellHeight)
# bottom and right dark border
self.DrawSetPen(self.ColEdgeDark)
self.DrawLine(x , y + self.CellHeight - 1, x + self.CellWidht - 1, y + self.CellHeight -1)
self.DrawLine(x + self.CellWidht - 1, y, x + self.CellWidht - 1, y + self.CellHeight - 1)
# cell content
self.DrawSetPen(self.GetCellPen(state, isfocus))
self.DrawRectangle(x + 1, y + 1, x + self.CellWidht - 2, y + self.CellHeight - 2)
def GetRect(self, pid, offset = 1):
"""
Get the drawing rect for an array id.
:param pid : the pattern id
:param offset : the pixel border offset
:return : int, int
"""
pid = int(pid)
col = pid / self.CellPerColumn
head = pid % self.CellPerColumn
return self.CellWidht * head + offset, self.CellHeight * col + offset
def GetID(self, x, y):
"""
Get the array id for a coord within the gadget.
:param x : local x
:param y : local y
:return : int
"""
col = (y - 1) / self.CellHeight
head = (x - 1) / self.CellWidht
return col * self.CellPerColumn + head
def IsFocus(self, x, y):
"""
Test if the cell coords are under the cursor.
:param x : local x
:param y : local y
:return : bool
"""
if (self.MouseX >= x and self.MouseX <= x + self.CellWidht and
self.MouseY >= y and self.MouseY <= y + self.CellHeight):
self.MouseX = c4d.NOTOK
self.MouseY = c4d.NOTOK
return True
else: return False
def InputEvent(self, msg):
"""
Fetch and store mouse clicks
:return : bool
"""
if isinstance(msg, c4d.BaseContainer):
if msg.GetLong(c4d.BFM_INPUT_DEVICE) == c4d.BFM_INPUT_MOUSE:
if msg.GetLong(c4d.BFM_INPUT_CHANNEL) == c4d.BFM_INPUT_MOUSELEFT:
base = self.Local2Global()
if base:
x = msg.GetLong(c4d.BFM_INPUT_X) - base['x']
y = msg.GetLong(c4d.BFM_INPUT_Y) - base['y']
pid = self.GetID(x, y)
if pid <= self.Host.PatternSize:
self.Host.Pattern[pid] = not self.Host.Pattern[pid]
self.Redraw()
return True
def FitGadegt(self):
"""
Fit the gadget size to the the array
"""
oldHeight = self.MinHeight
self.CellPerColumn = int((self.Width - 2) / self.CellWidht)
self.Columns = math.ceil(self.Host.PatternSize / self.CellPerColumn) + 1
self.MinHeight = int(fhp.IDC_SELECTLOOP_GADGET_MINH * self.Columns) + 3
self.MinWidht = int(fhp.IDC_SELECTLOOP_GADGET_MINW)
self.BorderWidth = self.CellWidht * self.CellPerColumn
if oldHeight != self.MinHeight: self.LayoutChanged()
def getColorVector(self, cid):
"""
Get a color vector from a color ID.
:param cid : The color ID
:return : c4d.Vector()
"""
dic = self.GetColorRGB(cid)
if dic: return c4d.Vector(float(dic['r']) * self.ColScale, float(dic['g'])* self.ColScale, float(dic['b'])* self.ColScale)
else: return c4d.Vector()