统计
  • 建站日期:2021-03-10
  • 文章总数:34 篇
  • 评论总数:2 条
  • 分类总数:3 个
  • 最后更新:5月30日
文章 Houdini

houdini veiwport HUD 显示信息

Luo7758
首页 Houdini 正文
广告

自定义视图信息显示 根据屏幕空间自适应位置,将代码拷贝到shelf tool 就可以。esc 键退出显示
相关帮助文档:https://www.sidefx.com/docs/houdini/hom/hou/ViewerStateTemplate.html

import hou, socket, os
from hutil.Qt import QtCore, QtWidgets, QtGui

_col   = hou.Color(1.0, 0.9, 0.2)
_size  = {'hip':7,'frange':7,'fps':7,'cframe':7,'pc':7,'res':7}
_margin = 2.0
_show  = {'hip':1,'frange':1,'fps':1,'cframe':1,'pc':1,'res':1}
_lbl   = {'hip':'HIP','frange':'Frame','fps':'FPS','cframe':'Frame','pc':'PC','res':'Res'}
_pc    = socket.gethostname()
_hip_n = ""   # 自定义 HIP 名(空=自动)
_pc_n  = ""   # 自定义机器名(空=自动)

class _HudState:
    def __init__(s, state_name, scene_viewer):
        s.sv = scene_viewer; s._d = None
    def _hex(s,c):
        r,g,b=[max(0,min(255,int(v*255)))for v in c.rgb()]
        return f"#{r:02X}{g:02X}{b:02X}"
    def _rt(s,t,c,sz,b=False):
        h=s._hex(c); be="<b>"if b else""; bee="</b>"if b else""
        return f'<font size={sz} color="{h}">{be}{t}{bee}</font>'
    def _hip(s):
        p=hou.hipFile.path(); return os.path.splitext(os.path.basename(p))[0]if p else"untitled"
    def _cam(s):
        try:
            if s.sv is None: return None
            vp=s.sv.curViewport()
            if vp is None: return None
            cr=vp.camera()
            cam=None
            if cr is not None:
                if isinstance(cr,hou.ObjNode): cam=cr
                elif isinstance(cr,str)and cr:
                    try: cam=hou.node(cr)
                    except: pass
            if cam is not None:
                for pn in('resx','res','resx_override'):
                    px=cam.parm(pn)
                    if px is not None:
                        py=cam.parm(pn.replace('x','y'))
                        if py is None: py=cam.parm('resy')
                        rx=int(px.eval()); ry=int(py.eval())if py else rx
                        return(rx,ry)
            _,_,w,h=vp.size(); return(int(w),int(h))
        except: return None
    def onEnter(s,k): pass
    def onResume(s,k):
        if s._d:
            for d in s._d.values():
                try: d.show(True)
                except: pass
    def onInterrupt(s,k): pass
    def onExit(s,k):
        if s._d:
            for d in s._d.values():
                try: d.show(False)
                except: pass
    def _gd(s):
        if s._d: return s._d
        s._d={k:hou.TextDrawable(s.sv,'h'+k)for k in('tl','tc','tr','bl','bc','br')}
        return s._d
    def onDraw(s,kw):
        global _col,_size,_margin,_show,_lbl,_pc,_hip_n,_pc_n
        try: h=kw['draw_handle']
        except: return
        try: sv=s.sv
        except: return
        if sv is None: return
        vp=sv.curViewport()
        if vp is None: return
        _,_,W,H=vp.size()
        if W<=0 or H<=0: return
        col=_col; mp=_margin/100.0
        tx={}
        if _show['hip']: tx['tl']=s._rt(f"{_lbl['hip']}: {_hip_n or s._hip()}",col,_size['hip'],True)
        if _show['frange']:
            a,b=hou.playbar.frameRange();a=int(a);b=int(b)
            tx['tc']=s._rt(f"{_lbl['frange']}: {a} - {b}",col,_size['frange'],True)
        if _show['fps']: tx['tr']=s._rt(f"{_lbl['fps']}: {hou.fps():.1f}",col,_size['fps'],True)
        if _show['pc']: tx['bl']=s._rt(f"{_lbl['pc']}: {_pc_n or _pc}",col,_size['pc'],True)
        if _show['res']:
            r=s._cam()
            if r: tx['bc']=s._rt(f"{_lbl['res']}: {r[0]}x{r[1]}",col,_size['res'],True)
        if _show['cframe']: tx['br']=s._rt(f"{_lbl['cframe']}: {int(hou.frame())}",col,_size['cframe'],True)
        if not tx: return
        r=s._cam()if _show['res']else None
        ox=oy=0.0; fw,fh=float(W),float(H)
        if r:
            cw,ch=r
            if cw>0 and ch>0:
                cr=float(cw)/ch; vr=float(W)/H
                if abs(cr-vr)>0.005:
                    if cr>vr: fh=W/cr; oy=(H-fh)/2.0
                    else: fw=H*cr; ox=(W-fw)/2.0
        M=max(6,int(min(fw,fh)*mp))
        D=s._gd()
        DT=hou.drawableTextOrigin
        UL,UR,BL,BR=DT.UpperLeft,DT.UpperRight,DT.BottomLeft,DT.BottomRight
        pm={
            'tl':(UL,(ox+M,oy+fh-M,0)),
            'tc':(UL,(ox+fw/2-100,oy+fh-M,0)),
            'tr':(UR,(ox+fw-M,oy+fh-M,0)),
            'bl':(BL,(ox+M,oy+M,0)),
            'bc':(BL,(ox+fw/2-100,oy+M,0)),
            'br':(BR,(ox+fw-M,oy+M,0)),
        }
        for key in('tl','tc','tr','bl','bc','br'):
            if key not in tx: D[key].show(False); continue
            D[key].show(True); o,a=pm[key]
            try: D[key].draw(h,{'text':tx[key],'multi_line':False,'origin':o,'translate':a,'color1':col})
            except: pass

class HudUI(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Viewport HUD"); self.setMinimumWidth(480)
        self.setWindowFlags(QtCore.Qt.Window)
        ly = QtWidgets.QVBoxLayout(self); ly.setSpacing(6)

        g1 = QtWidgets.QGroupBox("显示"); gg1 = QtWidgets.QGridLayout(g1); gg1.setSpacing(4)
        gg1.addWidget(QtWidgets.QLabel(""),0,0)
        gg1.addWidget(QtWidgets.QLabel("标签"),0,1)
        gg1.addWidget(QtWidgets.QLabel("字号"),0,2)

        self.cb = {}; self.le = {}; self.sz = {}
        items = [('hip','hip'),('frange','frange'),('fps','fps'),
                 ('cframe','cframe'),('pc','pc'),('res','res')]
        for row,(k,pos) in enumerate(items,1):
            cb=QtWidgets.QCheckBox(pos); cb.setChecked(_show[k]); cb.toggled.connect(self._sync)
            self.cb[k]=cb; gg1.addWidget(cb,row,0)
            le=QtWidgets.QLineEdit(_lbl[k]); le.setMinimumWidth(100); le.editingFinished.connect(self._sync)
            self.le[k]=le; gg1.addWidget(le,row,1)
            sp=QtWidgets.QSpinBox(); sp.setRange(4,20); sp.setValue(_size[k]); sp.setMaximumWidth(50)
            sp.valueChanged.connect(self._sync)
            self.sz[k]=sp; gg1.addWidget(sp,row,2)
        ly.addWidget(g1)

        gn = QtWidgets.QGroupBox("自定义名称(空=自动)"); gnl = QtWidgets.QGridLayout(gn); gnl.setSpacing(4)
        gnl.addWidget(QtWidgets.QLabel("HIP"),0,0)
        self.le_hip = QtWidgets.QLineEdit(_hip_n); self.le_hip.editingFinished.connect(self._sync); gnl.addWidget(self.le_hip,0,1)
        gnl.addWidget(QtWidgets.QLabel("PC"),1,0)
        self.le_pc = QtWidgets.QLineEdit(_pc_n); self.le_pc.editingFinished.connect(self._sync); gnl.addWidget(self.le_pc,1,1)
        ly.addWidget(gn)

        g2=QtWidgets.QGroupBox("样式"); gg2=QtWidgets.QGridLayout(g2); gg2.setSpacing(6)
        gg2.addWidget(QtWidgets.QLabel("边距%"),0,0)
        self.sm=QtWidgets.QDoubleSpinBox(); self.sm.setRange(0.5,15); self.sm.setValue(_margin)
        self.sm.valueChanged.connect(self._sync); gg2.addWidget(self.sm,0,1)
        self.bc=QtWidgets.QPushButton(); self._uc(); self.bc.clicked.connect(self._pick)
        gg2.addWidget(self.bc,1,0,1,2); ly.addWidget(g2)

    def _uc(self):
        r,g,b=[int(v*255)for v in _col.rgb()]
        self.bc.setStyleSheet(f"background:rgb({r},{g},{b});min-height:22px;border:1px solid #555;border-radius:3px")
    def _pick(self):
        global _col
        c=QtWidgets.QColorDialog.getColor(QtGui.QColor(*[int(v*255)for v in _col.rgb()]),self,"颜色")
        if c.isValid(): _col=hou.Color(c.redF(),c.greenF(),c.blueF()); self._uc(); self._sync()
    def _sync(self,*_):
        global _show,_lbl,_size,_margin,_hip_n,_pc_n
        for k in _show:
            _show[k]=self.cb[k].isChecked()
            _lbl[k]=self.le[k].text().strip()or k
            _size[k]=self.sz[k].value()
        _margin=self.sm.value()
        _hip_n=self.le_hip.text().strip()
        _pc_n=self.le_pc.text().strip()
    def _start(self):
        for old in("hud_tool","hud_ui","hud_ctrl"):
            try: hou.ui.unregisterViewerState(old)
            except: pass
        t=hou.ViewerStateTemplate("hud_tool","HUD",hou.objNodeTypeCategory()); t.bindFactory(_HudState)
        hou.ui.registerViewerState(t)
        sv=hou.ui.paneTabOfType(hou.paneTabType.SceneViewer)
        if sv: sv.setCurrentState("hud_tool",wait_for_exit=False)
    def _stop(self):
        try: hou.ui.unregisterViewerState("hud_tool")
        except: pass
    def showEvent(self,e):
        self._sync(); self._start()
    def closeEvent(self,e):
        self.hide(); e.ignore()  # 只隐藏,HUD 继续运行

# 删除旧窗口
for w in QtWidgets.QApplication.topLevelWidgets():
    if w.objectName() == "ViewportHUD":
        w.close(); w.deleteLater()

# 强制重建确保 UI 最新
hou.session._hud_panel = None
_win = HudUI()
_win.setObjectName("ViewportHUD")
hou.session._hud_panel = _win
if not _win.isVisible():
    _win._start()
_win.show(); _win.raise_()


版权说明
文章采用: 《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权。
版权声明:未标注转载均为本站原创,转载时请以链接形式注明文章出处。如有侵权、不妥之处,请联系站长删除。敬请谅解!

-- 展开阅读全文 --
deadline 运行houdini python脚本任务
下一篇 »
为了防止灌水评论,登录后即可评论!

HI ! 请登录
注册会员,享受下载全站资源特权。

今日事今日毕

标签

腾讯云

广告