奇怪!但的确是真的:关于以sp_开头的表

本文介绍了一个关于SQL Server的有趣特性:在master数据库中创建以'sp_'开头的表,可以从其他数据库对其进行读写操作。这一特性在特定场景下非常实用,例如收集多个数据库的日志信息。

Strange but True: sp_ tables

 

http://sqlblogcasts.com/blogs/davidwimbush/archive/2010/09/22/strange-but-true-sp-tables.aspx

奇怪!但的确是真的:sp_tables

I came across a bit of an eye-opener the other day in the SQL Server 2008 Internals book. You know how you can create your own stored proc in master with a name that starts with 'sp_' and then you can call it from any other database? Well if you create a table in master with a name that starts with 'sp_' you can read and write to it from any database too. Try this out:

在我读SQL Server 2008 Internals bookSQL Server2008内幕)的第二天时碰到了一个让我开眼界的东东。大家知道我们可以在master库中创建以‘sp_’开头的自定义存储过程,该存储过程可以在别的库中调用。你是否也可以在master库中创建以‘sp_’开头的表,该表可以在别的库中进行读写呢?试试看:

(译者注:该语句同样可以在SQL Server2005中运行。)

 

use master;

 

go

 

create table dbo.sp_temp

(

        tempid        int                not null

        , tempdata    varchar(10)        not null

);

go

 

use <someuserdatabase>;

go

 

insert  dbo.sp_temp

        (tempid, tempdata)

values  (1, 'One');

 

select  *

from    dbo.sp_temp;

go

 

use master;

go

 

drop table dbo.sp_temp;

go

It doesn't work if the table name doesn't start with 'sp_'. The example in the book (page 190) was about capturing the output from DBCC LOGINFO for all databases into a table for further analysis. This tool probably shouldn't become your new hammer for use on every screw in sight but it's very handy in certain circumstances.

如果表名不以‘sp_’开头,上述语句将不能工作。该书中190页的例子就是在所有数据库中获取DBCC LOGINFO的输出结果到一个表中以供进一步分析。你或许不能随意使用这个工具(特性)但是在某些特定的场合中该工具不失为你的一个“法宝”。

from PySide2 import QtGui from PySide2 import QtWidgets, QtCore from shiboken2 import wrapInstance from maya.app.general.mayaMixin import MayaQWidgetDockableMixin from maya import OpenMayaUI as omui import maya.OpenMaya as om import maya.cmds as cmds import maya.mel as mel import os, platform, subprocess, sys import xml.dom.minidom as xml # 用于XML设置 DEBUG = False PRNT_STRING = "<RizomUV桥接工具>" # 日志前缀汉化 try: # Python 3 from . import scriptlist except ImportError: import scriptlist class Settings(): def __init__(self): config_path = os.path.join('%s/RizomBridge' % os.getenv('APPDATA')) config_file = 'uisettings.xml' # 脚本路径设置 rizom_script_path = os.path.join(config_path, "MayaRizomBridgeScript.lua") self.rizom_script_path = rizom_script_path.replace('\\', '/') self.apppath = None self.config_file_path = os.path.join(config_path, config_file) self.check_config_exists(config_path) try: self.read_settings() except: print("<RizomUV桥接工具> 读取设置失败,正在创建新的xml文件。") # 日志汉化 self.set_defaults() self.save_xml() self.read_settings() self.exportFile = os.path.join(config_path, self.objname) self.exportFile = self.exportFile.replace('\\', '/') def read_settings(self): doc = xml.parse(self.config_file_path) ui_app = doc.getElementsByTagName("Application")[0] self.apppath = ui_app.getAttribute("apppath") self.objname = ui_app.getAttribute("objname") self.upaxis = ui_app.getAttribute("upaxis") self.loaduvs = self.str_to_bool(ui_app.getAttribute("loaduvs")) self.useuvlink = self.str_to_bool(ui_app.getAttribute("useuvlink")) self.fixuvnames = self.str_to_bool(ui_app.getAttribute("fixuvnames")) ui_packer = doc.getElementsByTagName("Packer")[0] self.quality = int(ui_packer.getAttribute("quality")) self.mutations = int(ui_packer.getAttribute("mutations")) self.margin = int(ui_packer.getAttribute("margin")) self.spacing = int(ui_packer.getAttribute("spacing")) self.resolution = int(ui_packer.getAttribute("resolution")) self.initscaleavg = self.str_to_bool(ui_packer.getAttribute("initscaleavg")) self.autofit = self.str_to_bool(ui_packer.getAttribute("autofit")) def set_defaults(self): self.objname = "MayaRizomExport.fbx" self.upaxis = "Y" self.loaduvs = True self.useuvlink = True self.fixuvnames = False self.quality = 2 self.mutations = 256 self.margin = 2 self.spacing = 2 self.resolution = 1024 self.initscaleavg = True self.autofit = True self.apppath = self.findall_rizom_installs()[-1] def save_xml(self): print(PRNT_STRING, f"将设置保存到磁盘: {self.config_file_path}") # 日志汉化 doc = xml.Document() root_element = doc.createElement("RizomBridge") element_application = doc.createElement("Application") element_application.setAttribute("apppath", str(self.apppath)) element_application.setAttribute("objname", str(self.objname)) element_application.setAttribute("upaxis", str(self.upaxis)) element_application.setAttribute("loaduvs", str(self.loaduvs)) element_application.setAttribute("useuvlink", str(self.useuvlink)) element_application.setAttribute("fixuvnames", str(self.fixuvnames)) element_packer = doc.createElement("Packer") element_packer.setAttribute("quality", str(self.quality)) element_packer.setAttribute("mutations", str(self.mutations)) element_packer.setAttribute("margin", str(self.margin)) element_packer.setAttribute("spacing", str(self.spacing)) element_packer.setAttribute("resolution", str(self.resolution)) element_packer.setAttribute("initscaleavg", str(self.initscaleavg)) element_packer.setAttribute("autofit", str(self.autofit)) doc.appendChild(root_element) root_element.appendChild(element_application) root_element.appendChild(element_packer) doc.writexml(open(self.config_file_path, 'w'), indent=" ", addindent=" ", newl='\n') def check_config_exists(self, config_path): print(PRNT_STRING, f"检查配置文件: {self.config_file_path}") # 日志汉化 if not os.path.exists(config_path): os.makedirs(config_path) if not os.path.exists(self.config_file_path): print(PRNT_STRING, "未找到配置文件。") # 日志汉化 self.set_defaults() self.save_xml() else: print(PRNT_STRING, "找到配置文件。") # 日志汉化 def findall_rizom_installs(self): """ 返回注册中所有存在的rizom.exe路径 """ try: import winreg except: self.manual_locate_rizom() return [self.apppath] key_path = "SOFTWARE\\Rizom Lab\\" parent_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path) installs = [] i = 0 while i < 1000: try: key = winreg.EnumKey(parent_key, i) try: exe_path = winreg.QueryValue(winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path + key), "rizomuv.exe") + ".exe" except FileNotFoundError: exe_path = "" if os.path.exists(exe_path): installs.append(exe_path.replace("\\", "/")) except WindowsError: break i += 1 print(PRNT_STRING, "在Windows注册中找到RizomUV安装路径:") # 日志汉化 for inst in sorted(installs): print(" ..", inst) return sorted(installs) def manual_locate_rizom(self): om.MGlobal.displayWarning(f"无法定位rizomuv.exe: {self.apppath}") # 提示汉化 fname = QtWidgets.QFileDialog.getOpenFileName(None, '定位rizomuv.exe', 'C:/Program Files/Rizom Lab/', "可执行文件 (*.exe)") # 对话框标题及过滤器汉化 self.apppath = fname[0] self.appver = self.get_version() self.save_xml() def get_version(self): """ 从文件夹名称读取版本号,返回列形式,例如 [2022, 2] """ # 注释汉化 return os.path.dirname(self.apppath).split()[-1].split('.') def check_lua_path(self): if not os.path.exists(self.rizom_script_path): with open(self.rizom_script_path, 'w') as f: if DEBUG: print(PRNT_STRING, f"在{self.rizom_script_path}创建空白lua文件") # 日志汉化 f.write('') def str_to_bool(self, s): if s == 'True': return True else: # 其他情况均返回False,否则可能返回None导致崩溃 return False class RizomUVBridgeWindow(MayaQWidgetDockableMixin, QtWidgets.QDialog): def __init__(self, rootWidget=None, *args, **kwargs): super(RizomUVBridgeWindow, self).__init__() self.conf = Settings() self.conf.check_lua_path() print("Rizom路径:", self.conf.apppath) # 日志汉化 self.setWindowTitle("桥接工具") # 窗口标题汉化 self.sj_num_selchange = cmds.scriptJob(parent=self.objectName(), event=['SelectionChanged', self.ui_update_uvchannels]) self.resize(250, 300) self.create_widgets() self.create_layouts() self.create_connections() self.exported_objects = [] self.ui_update_uvchannels() self.cleanse_namespaces() self.config_updated = False if not os.path.exists(self.conf.apppath): self.conf.manual_locate_rizom() v = self.conf.get_version() self.btn_run.setText(f'运行RizomUV {v[0]}.{v[1]}') # 按钮文本汉化 rizom_link_path = os.path.dirname(self.conf.apppath) + '/RizomUVLink' self.port = None if rizom_link_path not in sys.path: sys.path.append(os.path.dirname(self.conf.apppath) + '/RizomUVLink') try: from RizomUVLink import CRizomUVLink self.link = CRizomUVLink() except: self.link = None def create_widgets(self): v = ".".join(self.conf.get_version()) self.btn_run = QtWidgets.QPushButton(f'运行RizomUV {v}', self) # 按钮文本汉化 self.btn_export = QtWidgets.QPushButton('导出', self) # 按钮文本汉化 self.btn_import = QtWidgets.QPushButton('导入', self) # 按钮文本汉化 self.cbx_use_link = QtWidgets.QCheckBox('尝试使用CRizomUVLink连接', self) # 复选框文本汉化 self.cbx_use_link.setChecked(self.conf.useuvlink) self.cbx_fix_set_names = QtWidgets.QCheckBox('导入时修复UV集名称', self) # 复选框文本汉化 self.cbx_fix_set_names.setChecked(self.conf.fixuvnames) if not os.path.exists(self.conf.exportFile): self.btn_import.setEnabled(False) # 导出设置组件 self.radioAxisY = QtWidgets.QRadioButton('Y轴') # 单选按钮文本汉化 self.radioAxisZ = QtWidgets.QRadioButton('Z轴') # 单选按钮文本汉化 if self.conf.upaxis == 'Y': self.radioAxisY.setChecked(True) else: self.radioAxisZ.setChecked(True) self.cbx_keepuv = QtWidgets.QCheckBox('加载现有UV', self) # 复选框文本汉化 self.cbx_keepuv.setChecked(self.conf.loaduvs) self.combo_scripts = QtWidgets.QComboBox(self) self.combo_scripts.addItem("无脚本") # 下拉框文本汉化 for s in scriptlist.scripts: self.combo_scripts.addItem(s[1]) # 工具组件 self.btn_fix_shell_normals = QtWidgets.QPushButton('将UV边界边设为硬边') # 按钮文本汉化 self.btn_edit_settings = QtWidgets.QPushButton('打开设置文件夹') # 按钮文本汉化 self.combo_pack_uvset = QtWidgets.QComboBox(self) self.btn_pack = QtWidgets.QPushButton('导出并打包UV', self) # 按钮文本汉化 self.combo_pack_quality = QtWidgets.QComboBox(self) self.combo_pack_quality.addItems(['低', '普通', '高', '较高', '极高']) # 下拉框文本汉化 self.combo_pack_quality.setCurrentIndex(self.conf.quality) self.slider_pack_uvmap = QtWidgets.QSlider(QtCore.Qt.Orientation(1)) self.slider_pack_uvmap.setMinimum(0) self.slider_pack_uvmap.setMaximum(5) self.slider_pack_uvmap.setValue(1) self.label_uvmap = QtWidgets.QLabel("1") self.dspin_pack_mutations = QtWidgets.QSpinBox() self.dspin_pack_mutations.setSingleStep(1) self.dspin_pack_mutations.setRange(1, 1000) self.dspin_pack_mutations.setWrapping(False) self.dspin_pack_mutations.setValue(self.conf.mutations) self.dspin_pack_resolution = QtWidgets.QSpinBox() self.dspin_pack_resolution.setSingleStep(8) self.dspin_pack_resolution.setRange(8, 8192) self.dspin_pack_resolution.setWrapping(False) self.dspin_pack_resolution.setValue(self.conf.resolution) self.dspin_pack_margin = QtWidgets.QSpinBox() self.dspin_pack_margin.setSingleStep(1) self.dspin_pack_margin.setWrapping(False) self.dspin_pack_margin.setValue(self.conf.margin) self.dspin_pack_spacing = QtWidgets.QSpinBox() self.dspin_pack_spacing.setSingleStep(1) self.dspin_pack_spacing.setWrapping(False) self.dspin_pack_spacing.setValue(self.conf.spacing) self.cbx_initial_scale_avg = QtWidgets.QCheckBox("使用'平均'初始缩放", self) # 复选框文本汉化 self.cbx_initial_scale_avg.setChecked(self.conf.initscaleavg) self.cbx_layout_scaling = QtWidgets.QCheckBox("布局:自动适配", self) # 复选框文本汉化 self.cbx_layout_scaling.setChecked(self.conf.autofit) def create_layouts(self): main_layout = QtWidgets.QVBoxLayout(self) grp_layout = QtWidgets.QVBoxLayout() grp_layout.addWidget(self.btn_run) grp_layout.addWidget(self.btn_export) grp_layout.addWidget(self.btn_import) grp_layout.addWidget(self.cbx_use_link) grp_layout.addWidget(self.cbx_fix_set_names) grp = QtWidgets.QGroupBox("UV操作") # 组框标题汉化 grp.setLayout(grp_layout) main_layout.addWidget(grp) # 导出设置 grp_layout = QtWidgets.QVBoxLayout() grp_layout.addWidget(self.cbx_keepuv) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("脚本")) # 标签文本汉化 hor_layout.addWidget(self.combo_scripts) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("上方向轴")) # 标签文本汉化 hor_layout.addWidget(self.radioAxisY) hor_layout.addWidget(self.radioAxisZ) grp_layout.addLayout(hor_layout) grp = QtWidgets.QGroupBox("导出设置") # 组框标题汉化 grp.setLayout(grp_layout) main_layout.addWidget(grp) # 工具 grp_layout = QtWidgets.QVBoxLayout() grp_layout.addWidget(self.btn_fix_shell_normals) grp_layout.addWidget(self.btn_edit_settings) grp = QtWidgets.QGroupBox("工具") # 组框标题汉化 grp.setLayout(grp_layout) main_layout.addWidget(grp) # UV打包 grp_layout = QtWidgets.QVBoxLayout() grp = QtWidgets.QGroupBox("UV打包") # 组框标题汉化 hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(self.btn_pack) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("要打包的UV集")) # 标签文本汉化 hor_layout.addWidget(self.combo_pack_uvset) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("打包质量")) # 标签文本汉化 hor_layout.addWidget(self.combo_pack_quality) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("迭代次数")) # 标签文本汉化 hor_layout.addWidget(self.dspin_pack_mutations) hor_layout.addWidget(QtWidgets.QLabel("分辨率")) # 标签文本汉化 hor_layout.addWidget(self.dspin_pack_resolution) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("边距")) # 标签文本汉化 hor_layout.addWidget(self.dspin_pack_margin) hor_layout.addWidget(QtWidgets.QLabel("间距")) # 标签文本汉化 hor_layout.addWidget(self.dspin_pack_spacing) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(self.cbx_initial_scale_avg) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(self.cbx_layout_scaling) grp_layout.addLayout(hor_layout) grp_layout.addStretch() grp.setLayout(grp_layout) main_layout.addWidget(grp) def create_connections(self): self.btn_run.clicked.connect(self.riz_run) self.btn_export.clicked.connect(self.riz_export) self.btn_import.clicked.connect(self.riz_import) self.btn_fix_shell_normals.clicked.connect(fix_shell_border_normals) self.btn_edit_settings.clicked.connect(self.browse_settings_location) self.cbx_keepuv.stateChanged.connect(self.set_config) self.slider_pack_uvmap.valueChanged.connect(self.ui_pack_update_labels) self.radioAxisY.clicked.connect(self.set_config) self.radioAxisZ.clicked.connect(self.set_config) self.dspin_pack_mutations.valueChanged.connect(self.set_config) self.dspin_pack_resolution.valueChanged.connect(self.set_config) self.dspin_pack_margin.valueChanged.connect(self.set_config) self.dspin_pack_spacing.valueChanged.connect(self.set_config) self.cbx_layout_scaling.stateChanged.connect(self.set_config) self.cbx_use_link.stateChanged.connect(self.set_config) self.cbx_fix_set_names.stateChanged.connect(self.set_config) self.btn_pack.clicked.connect(self.riz_pack) return def riz_run(self): # 确认应用程序路径 if not os.path.exists(self.conf.apppath): self.manual_locate_rizom() if self.link and self.cbx_use_link.isChecked(): self.port = self.link.RunRizomUV() print(PRNT_STRING, f"RizomUV {self.link.RizomUVVersion()}链接已建立。正在TCP端口{self.port}监听命令") # 日志汉化 else: # 链接不可用时使用原始方法 print(PRNT_STRING, "RizomUV链接不可用。将使用LUA脚本文件通信。") # 日志汉化 cmd = '"' + self.conf.apppath + '" -cf "' + self.conf.rizom_script_path + '"' print(cmd) if platform.system() == "Windows": self.sp = subprocess.Popen(cmd, shell=True) else: self.sp = subprocess.Popen(["open", "-a", self.conf.apppath, "-cf", self.conf.rizom_script_path]) self.btn_export.setEnabled(True) return def riz_pack(self): # 导出模型不加载脚本 current_uv = self.combo_pack_uvset.currentText() exported = self.riz_export(False, False) if not exported: return # 根据GUI选项构建LUA代码 cmd = '' # 重复使用的文本块 cmd_properties_prefix = 'ZomIslandGroups({Mode="SetGroupsProperties", WorkingSet="Visible", MergingPolicyString="A_ADD|AIB_ADD_A_VALUE_B|B_CLONE", GroupPaths={ "RootGroup" }, ' # 加载模型 cmd += 'ZomLoad({File={Path="'+self.conf.exportFile+'", ImportGroups=true, XYZUVW=true, UVWProps=true}})\n' cmd += 'ZomUvset({Mode="SetCurrent", Name="%s"})\n' % current_uv cmd += cmd_properties_prefix + 'Properties={Pack={Rotate={Step=90}}}})\n' cmd += cmd_properties_prefix + 'Properties={Pack={Rotate={Mode=0}}}})\n' margin = float(self.dspin_pack_margin.value()) / self.dspin_pack_resolution.value() spacing = float(self.dspin_pack_spacing.value()) / self.dspin_pack_resolution.value() cmd += cmd_properties_prefix + 'Properties={Pack={SpacingSize=%f}}})\n' % spacing cmd += cmd_properties_prefix + 'Properties={Pack={MarginSize=%f}}})\n' % margin quality = [128, 256, 512, 1024, 2048] cmd += cmd_properties_prefix + 'Properties={Pack={Resolution=%i}}})\n' % quality[self.combo_pack_quality.currentIndex()] cmd += cmd_properties_prefix + 'Properties={Pack={MaxMutations=%i}}})\n' % self.dspin_pack_mutations.value() init_scale = 0 if self.cbx_initial_scale_avg.isChecked(): init_scale = 2 layout_scale = 0 if self.cbx_layout_scaling.isChecked(): layout_scale = 2 cmd += 'ZomSet({Path="Prefs.PackOptions.__ScalingMode", Value=%i})\n' % init_scale cmd += 'ZomSave({File={Path="c:/users/root/appdata/local/temp/MayaRizomExport.fbx", UVWProps=true}, __UpdateUIObjFileName=true})\n' cmd += 'ZomIslandGroups({Mode="DistributeInTilesEvenly", WorkingSet="Visible&Flat", MergingPolicyString="A_ADD|AIB_ADD_A_VALUE_B|B_CLONE", UseTileLocks=true, UseIslandLocks=true})\n' cmd += 'ZomPack({RootGroup="RootGroup", WorkingSet="Visible&Flat", ProcessTileSelection=false, RecursionDepth=1, Translate=true, LayoutScalingMode=%i, Scaling={Mode=%i}})\n' % (layout_scale, init_scale) if DEBUG: print(cmd) self.write_to_lua_file(cmd) return def fbx_export(self): # FBX导出 if not cmds.pluginInfo("fbxmaya", loaded=True, query=True): cmds.loadPlugin("fbxmaya") cmds.undoInfo(openChunk=True) mel.eval('ConvertInstanceToObject;') # 这是唯一需要撤销的命令 mel.eval('FBXExportSmoothingGroups -v true;') mel.eval('FBXExportTriangulate -v false;') mel.eval('FBXExportSmoothMesh -v false;') mel.eval('FBXExportUpAxis {};'.format(self.conf.upaxis)) print(f'FBXExport -s -f "{self.conf.exportFile}";') mel.eval(f'FBXExport -s -f "{self.conf.exportFile}";') try: cmds.undo() except RuntimeError as RE: # 没有更多可撤销的命令 pass # 结束FBX导出 return def riz_export(self, use_script=True, load_model=True): if self.link and self.cbx_use_link.isChecked(): print("Rizom链接版本", self.link.Version()) self.exported_objects = cmds.ls(selection=True, tr=True) # FBX导出 self.fbx_export() if not self.port: self.riz_run() params = { "File.Path": self.conf.exportFile, "File.XYZUVW": True, # 加载3D+UV数据(使用File.XYZ仅加载3D数据) "File.UVWProps": True, # 加载UV属性(如固定、纹理密度设置等) "File.ImportGroups": True, # 加载岛组层级 "__Focus": True, # 在视口中聚焦加载的网格 } self.link.Load(params) if DEBUG: print("<RIZOM> 导出至:", self.conf.exportFile) # 日志汉化 cmds.select(self.exported_objects) # 启用导入按钮(如果之前禁用) self.btn_import.setEnabled(True) else: # 传统方法 # print("<RIZOM> 正在导出模型") # 日志汉化 self.cleanse_namespaces() # 强制清理 self.exported_objects = cmds.ls(selection=True, tr=True) if not self.exported_objects: return False # 删除历史记录(防止存在空组被此操作移除) # 否则导入时会被清除,导致对象计数不匹配 cmds.bakePartialHistory() cmd = '' # 导出选项 if load_model: if self.cbx_keepuv.isChecked(): cmd += 'ZomLoad({File={Path="'+self.conf.exportFile+'", ImportGroups=true, XYZUVW=true, UVWProps=true}})\n' else: cmd += 'ZomLoad({File={Path="'+self.conf.exportFile+'", ImportGroups=true, XYZ=true}, NormalizeUVW=true})\n' # 添加脚本 if self.combo_scripts.currentIndex() and use_script is True: script_name = scriptlist.scripts[self.combo_scripts.currentIndex()-1][0] script_path = os.path.join(os.path.dirname(__file__), 'lua_scripts/%s' % script_name) with open(script_path, 'r') as lua_script: cmd += lua_script.read() if DEBUG: print("<RizomUV桥接工具>", cmd) # 日志汉化 # FBX导出 self.fbx_export() if DEBUG: print("<RIZOM> 导出至:", self.conf.exportFile) # 日志汉化 cmds.select(self.exported_objects) self.write_to_lua_file(cmd) self.btn_import.setEnabled(True) # 如果有显著更改,将配置写入磁盘 if self.config_updated == True: self.conf.save_xml() return True def riz_import(self): if not os.path.exists(self.conf.exportFile): om.MGlobal.displayError(f"无法找到导出文件: {self.conf.exportFile}") # 错误提示汉化 self.btn_import.setEnabled(False) if self.cbx_use_link.isChecked(): if self.link: try: self.link.Save({"File.Path": self.conf.exportFile}) except RuntimeError as RE: cmds.error('无法通过Python链接向Rizom发送保存命令。导出时是否启用了链接?') # 错误提示汉化 # FBX导入 namespace = ':RIZOMUV' if not cmds.namespace(ex=namespace): cmds.namespace(add=namespace) cmds.namespace(set=namespace) mel.eval('FBXImportMode -v add;') mel.eval(f'FBXImport -f "{self.conf.exportFile}";') # 结束FBX导入 imported_objects = cmds.ls('RIZOMUV:*', long=True, type="transform") original_matches = [] for riz_obj in imported_objects: print("导入的对象名称", riz_obj) # 日志汉化 original = riz_obj.replace('RIZOMUV:', '') original_matches.append(original) # 列出每个项目的UV集,无UV集则跳过(排除组节点等对象) original_uvsets = cmds.polyUVSet(original, allUVSets=True, q=True) imported_uvsets = cmds.polyUVSet(riz_obj, allUVSets=True, q=True) if original_uvsets: # 检查名称 # if self.cbx_fix_set_names.isChecked(): for i in range(len(original_uvsets)): try: if not original_uvsets[i] == imported_uvsets[i]: cmds.polyUVSet(riz_obj, rename=True, uvSet=imported_uvsets[i], newUVSet=original_uvsets[i]) except IndexError: # 可能因Maya奇怪的bug导致(polyUVSet命令列出的UV集数量与UV集编辑器中不同) print("UV集索引错误。对象的UV集数量似乎不匹配") # 日志汉化 print("原始UV集:", original_uvsets, original) print("导入的UV集:", imported_uvsets, riz_obj) pass try: cmds.polyTransfer(original, ao=riz_obj, ch=False, uv=True) except RuntimeError as rt: print(f"<RizomUV桥接工具> 无法从{riz_obj}向{original}传输UV") # 日志汉化 if DEBUG: print(f"<RizomUV桥接工具> 从{riz_obj}向{original}传输UV") # 日志汉化 cmds.select(original_matches) cmds.bakePartialHistory() cmds.delete(':RIZOMUV:*') cmds.namespace(rm=':RIZOMUV') return def browse_settings_location(self): os.startfile(os.path.dirname(self.conf.config_file_path)) def ui_pack_update_labels(self): print("值已更改") # 日志汉化 self.label_uvmap.setText(str(self.slider_pack_uvmap.value())) def ui_update_uvchannels(self): sel_obj = cmds.ls(sl=True, tr=True) if not sel_obj: self.combo_pack_uvset.clear() return uvsets = cmds.polyUVSet(sel_obj[0], allUVSets=True, q=True) current_set = cmds.polyUVSet(sel_obj[0], cuv=True, q=True) if uvsets: print(uvsets) self.combo_pack_uvset.clear() self.combo_pack_uvset.addItems(uvsets) self.combo_pack_uvset.setCurrentIndex(uvsets.index(current_set[0])) def cleanse_namespaces(self): """ 第一步 -- 尝试删除所有现有RIZOMUV命名空间直到失败,这应该能清除像 RIZOMUV:RIZOMUV:RIZOMUV这样的嵌套实例 """ fail = False while(not fail): try: cmds.namespace(rm=':RIZOMUV', mnr=True) except: fail = True """ 第二步 -- 在某些场景中,命名空间可能被重命名为RIZOMUV1、RIZOMUV2、RIZOMUV3等 因此需要查找并删除这些残留 """ """ 第二步(更新)-- 尝试删除除RIZOM之外的其他命名空间,因为存在其他命名空间可能导致导入失败 """ c = cmds.listRelatives(ad=True) if not c: return for obj in c: ns_split = obj.split(':') if len(ns_split)>1: result = cmds.confirmDialog( m="选中的对象已分配命名空间。\n" # 对话框文本汉化 "使用工具前必须移除这些命名空间\n" "是否为您删除?(包括未选中的对象)\n\n" "对象上的命名空间:\n%s" % ns_split[0], button=['移除', '取消'] # 按钮文本汉化 ) if result == '移除': cmds.namespace(rm=ns_split[0], mnr=True) else: return return def write_to_lua_file(self, command): with open(self.conf.rizom_script_path, 'w') as f: f.write(command) print("<RIZOM> 已将命令写入lua文件:", self.conf.rizom_script_path) # 日志汉化 for line in command.split("\n"): print("\t", line) return def set_config(self): self.conf.loaduvs = self.cbx_keepuv.isChecked() if self.radioAxisY.isChecked(): self.conf.upaxis = "Y" else: self.conf.upaxis = "Z" self.conf.mutations = self.dspin_pack_mutations.value() self.conf.resolution = self.dspin_pack_resolution.value() self.conf.margin = self.dspin_pack_margin.value() self.conf.spacing = self.dspin_pack_spacing.value() self.conf.autofit = self.cbx_layout_scaling.isChecked() self.conf.fixuvnames = self.cbx_fix_set_names.isChecked() self.conf.useuvlink = self.cbx_use_link.isChecked() self.config_updated = True self.conf.save_xml() def closeEvent(self, event): self.conf.save_xml() def GetMayaWidget(): """ 返回Maya主窗口部件的Python对象 """ # 注释汉化 main_window_ptr = omui.MQtUtil.mainWindow() if sys.version_info.major >= 3: return wrapInstance(int(main_window_ptr), QtWidgets.QWidget) else: return wrapInstance(long(main_window_ptr), QtWidgets.QWidget) def fix_shell_border_normals(): obj_list = cmds.ls(sl=True, o=True) all_final_borders = [] for sub_obj in obj_list: cmds.select(sub_obj, r=True) cmds.polyNormalPerVertex(ufn=True) cmds.polySoftEdge(sub_obj, a=180, ch=1) print("全部软化") # 日志汉化 # 选择对象UV cmds.select(sub_obj + '.map[*]') mel.eval('polySelectBorderShell 1;') uv_border = cmds.polyListComponentConversion(te=True, internal=True) uv_border = cmds.ls(uv_border, fl=True) final_border = [] # 特殊过滤 for curEdge in uv_border: edge_uvs = cmds.polyListComponentConversion(curEdge, tuv=True) edge_uvs = cmds.ls(edge_uvs, fl=True) if len(edge_uvs) > 2: final_border.append(curEdge) cmds.polySoftEdge(final_border, a=0, ch=1) all_final_borders.append(final_border) cmds.select(cl=True) for sel_l in all_final_borders: cmds.select(sel_l, add=True) cmds.hilite(obj_list) def run(): scriptJobs = cmds.scriptJob(listJobs=True) for sj in scriptJobs: if "RizomBridge" in sj: print(PRNT_STRING, f"终止已存在的scriptJob: {sj}") # 日志汉化 cmds.scriptJob(kill=int(sj.split(':')[0])) d = RizomUVBridgeWindow() d.show(dockable=True) if __name__ == "__main__": run()
最新发布
11-02
root@localhost:~/5.15-13# tools/bazel run //common:kernel_aarch64_dist --config=fast INFO: Analyzed target //common:kernel_aarch64_dist (0 packages loaded, 0 targets configured). INFO: Found 1 target... ERROR: /root/5.15-13/common/BUILD.bazel:52:22: Building kernel kernel_aarch64 failed: (Exit 2): bash failed: error executing command (from target //common:kernel_aarch64) /bin/bash -c ... (remaining 1 argument skipped) /root/5.15-13/common/kernel/sys.c:3078:29: error: no member named 'fp_regs' in 'struct reg_data' memcpy(&g_reg_data->fp_regs, &fp, sizeof(struct user_fpsimd_state)); ~~~~~~~~~~ ^ /root/5.15-13/common/kernel/sys.c:3100:11: error: assigning to 'struct perf_event *' from incompatible type 'typeof (*(*bp_ptr))' (aka 'struct perf_event'); remove * cpu_event = *this_cpu_ptr(*bp_ptr); ^ ~~~~~~~~~~~~~~~~~~~~~~ /root/5.15-13/common/kernel/sys.c:3125:8: error: incompatible pointer types assigning to 'struct perf_event *' from 'struct perf_event **'; dereference with * [-Werror,-Wincompatible-pointer-types] new_bp = register_wide_hw_breakpoint(&new_attr, hwbp_handler, current); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * /root/5.15-13/common/kernel/sys.c:3132:31: error: incompatible pointer types passing 'struct perf_event *' to parameter of type 'struct perf_event **'; remove * [-Werror,-Wincompatible-pointer-types] unregister_wide_hw_breakpoint(*bp_ptr); ^~~~~~~ /root/5.15-13/common/include/linux/hw_breakpoint.h:76:73: note: passing argument to parameter 'cpu_events' here extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events); ^ /root/5.15-13/common/kernel/sys.c:3138:18: error: assigning to 'struct perf_event *' from incompatible type 'typeof (*(new_bp))' (aka 'struct perf_event'); remove * info->sample_hbp = *this_cpu_ptr(new_bp); ^ ~~~~~~~~~~~~~~~~~~~~~ /root/5.15-13/common/kernel/sys.c:3159:11: error: no member named 'b极_addr' in 'struct perf_event_attr'; did you mean 'bp_addr'? orig_attr.b极_addr = info->original_addr; ^~~~~~~~ bp_addr /root/5.15-13/common/include/uapi/linux/perf_event.h:423:10: note: 'bp_addr' declared here __u64 bp_addr; ^ /root/5.15-13/common/kernel/sys.c:3162:9: error: incompatible pointer types assigning to 'struct perf_event *' from 'struct perf_event **'; dereference with * [-Werror,-Wincompatible-pointer-types] orig_bp = register_wide_hw_breakpoint(&orig_attr, hwbp_handler, current); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * /root/5.15-13/common/kernel/sys.c:3169:31: error: incompatible pointer types passing 'struct perf_event *' to parameter of type 'struct perf_event **'; remove * [-Werror,-Wincompatible-pointer-types] unregister_wide_hw_breakpoint(*bp_ptr); ^~~~~~~ /root/5.15-13/common/include/linux/hw_breakpoint.h:76:73: note: passing argument to parameter 'cpu_events' here extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events); ^ /root/5.15-13/common/kernel/sys.c:3175:18: error: assigning to 'struct perf_event *' from incompatible type 'typeof (*(orig_bp))' (aka 'struct perf_event'); remove * info->sample_hbp = *this_cpu_ptr(orig_bp); ^ ~~~~~~~~~~~~~~~~~~~~~~ /root/5.15-13/common/kernel/sys.c:3334:31: error: incompatible pointer types passing 'struct perf_event *' to parameter of type 'struct perf_event **'; take the address with & [-Werror,-Wincompatible-pointer-types] unregister_wide_hw_breakpoint(bp); ^~ & /root/5.15-13/common/include/linux/hw_breakpoint.h:76:73: note: passing argument to parameter 'cpu_events' here extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events); ^ /root/5.15-13/common/kernel/sys.c:3423:31: error: incompatible pointer types passing 'struct perf_event *' to parameter of type 'struct perf_event **'; take the address with & [-Werror,-Wincompatible-pointer-types] unregister_wide_hw_breakpoint(bp); ^~ & /root/5.15-13/common/include/linux/hw_breakpoint.h:76:73: note: passing argument to parameter 'cpu_events' here extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events); ^ /root/5.15-13/common/kernel/sys.c:3499:4: error: incompatible pointer types assigning to 'struct perf_event *' from 'struct perf_event **'; dereference with * [-Werror,-Wincompatible-pointer-types] bp = register_wide_hw_breakpoint(&attr, hwbp_handler, tsk); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * /root/5.15-13/common/kernel/sys.c:3507:22: error: assigning to 'struct perf_event *' from incompatible type 'typeof (*(bp))' (aka 'struct perf_event'); remove * new_info->sample_hbp = *this_cpu_ptr(bp); // 关联断点句柄 ^ ~~~~~~~~~~~~~~~~~ 13 errors generated. make[2]: *** [/root/5.15-13/common/scripts/Makefile.build:287: kernel/sys.o] Error 1 make[1]: *** [/root/5.15-13/common/Makefile:1953: kernel] Error 2 make: *** [Makefile:244: __sub-make] Error 2 [6 / 14] 2 actions running Preparing for module build //common:kernel_aarch64_modules_prepare; 14s linux-sandbox Building UAPI kernel headers kernel_aarch64_uapi_headers; 14s linux-sandbox 仔细阅读linux文档 在仔细阅读报错原因 完整修复好发给我
07-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值