I had 2 questions in which I am not sure if this can by done in-scene using python.
My Maya version is not installed with any Mental Ray. There are times in which when I opened files (that was installed with Mental Ray), I keep getting errors such as:
// Warning: file: /apps/Linux64/aw/maya2014/scripts/others/supportRenderers.mel line 77: The renderer "mentalRay" used by this scene, is not currently available. The Maya Software renderer will be used instead. //
// Error: file: /apps/Linux64/aw/maya2014/scripts/others/supportRenderers.mel line 82: setAttr: The attribute 'defaultRenderGlobals.currentRenderer' is locked or connected and cannot be modified. //
// Error: file: /apps/Linux64/aw/maya2014/scripts/others/unifiedRenderGlobalsWindow.mel line 415: The renderer mentalRay is not registered yet. //
// Error: line 1: The renderer mentalRay is not registered yet. //
I tried using the following code to 'rectify' the issue:
list = cmds.listAttr("defaultRenderGlobals", l=True)
for item in list:
cmds.setAttr("defaultRenderGlobals." + item, l=False)
mel.eval('updateCurrentRendererSel("unifiedRenderGlobalsRendererSelOptionMenu");')
mel.eval('loadPreferredRenderGlobalsPreset("mayaHardware");')
but then I will get another bunch of error if I tried to open up my Render Settings
//Error: Object ‘tabForm’ not found.
And so, are there any ways in which this can be remedied in-scene
Attached is the screenshot:
Note: See the "Update" section below in this answer to find the full solution.
Why don't you just try unlocking and setting the currentRenderer value using setAttr itself.
cmds.setAttr("defaultRenderGlobals.currentRenderer", l=False)
cmds.setAttr("defaultRenderGlobals.currentRenderer", "mayaHardware", type="string")
You are getting the error //Error: Object ‘tabForm’ not found. because the render settings window failed to load, probably because of unregistered mentalRay. So AVOID calling the following until current renderer is changed:
mel.eval('updateCurrentRendererSel("unifiedRenderGlobalsRendererSelOptionMenu");')
mel.eval('loadPreferredRenderGlobalsPreset("mayaHardware");')
Update:
From the updates in the question and the comments below, we come to understand that the problem here is that Maya fails to construct the render settings window's UI properly when it encounters a missing renderer or render settings errors. This leads to parent UI components, like the tabs and frames to not being built. As a result, when the renderer is switched, the render settings UI tries to load the corresponding settings into these tabs but cannot find them and stops.
To work around this, we can just set the render settings we want, delete the render settings window's UI completely and reload it. I wrote a quick function for this. This will fix it.
import maya.cmds as cmds
import maya.mel as mel
def remake_render_settings_ui(renderer="mayaSoftware"):
""" Remakes the render settings window """
# Unlock the render globals' current renderer attribute
cmds.setAttr("defaultRenderGlobals.currentRenderer", l=False)
# Sets the current renderer to given renderer
cmds.setAttr("defaultRenderGlobals.currentRenderer", renderer, type="string")
# Deletes the render settings window UI completely
if cmds.window("unifiedRenderGlobalsWindow", exists=True):
cmds.deleteUI("unifiedRenderGlobalsWindow")
# Remake the render settings UI
mel.eval('unifiedRenderGlobalsWindow;')
if __name__ == "__main__":
remake_render_settings_ui(renderer="mayaHardware")
Caveat: This will not prevent the UI from getting lost again if the faulty renderer is somehow selected again. To prevent that, it is better to unload the renderer's plugin. In any case, if the above method is called again, the window should be fixed.
Hope this was useful.
There are a few problems that arises in the Render Settings while opening a scene file that contains traces of Mental Ray in a machine installed with no Mental Ray plugin
For some reasons, despite unlocking and setting a renderer in the defaultRenderGlobals in the scene, the render settings will continue to have problems as mentioned in the thread post or comments in kartikg3 answer.
I found a workaround which is -
Unlock the defaultRenderGlobals
Save the said file Delete any existing unifiedRenderGlobalsWindow
UI + a few more mel commands
Reload/Re-opening the scene
Seems to me that doing the first 2 steps within the scene, it does not rectify the issues in the Render Settings window unless I either close the current scene file by opening a new file session or reopen the file itself...
import maya.cmds as cmds
import maya.mel as mel
def unlockRenderer(renderer="mayaHardware2"):
print "Unlocking and resetting current renderer"
# Unlock the render globals' current renderer attribute
cmds.setAttr("defaultRenderGlobals.currentRenderer", l=False)
# Sets the current renderer to given renderer
cmds.setAttr("defaultRenderGlobals.currentRenderer", renderer, type="string")
def saveFile():
# Prompts User to resave the file, removing traces of Mental Ray
mel.eval('SaveSceneAs;')
def reloadScene():
recentFiles = []
try:
recentFiles = cmds.optionVar( query = 'RecentFilesList' )
except:
cmds.error("No recent files found!")
curFile = cmds.file(query =True, loc = True)
if curFile == "unknown":
cmds.confirmDialog(title = 'Reload Scene', message = ('Reload Last Opened Scene?\n\n' + recentFiles[len(recentFiles)-1]), button = ['Cancel','OK'], defaultButton = 'OK', cancelButton = 'Cancel', dismissString = 'Cancel' )
cmds.file( str(recentFiles[len(recentFiles)-1]), force = True, open = True)
print "Opening Last Recent File - ", recentFiles[len(recentFiles)-1]
else:
cmds.confirmDialog(title = 'Reload Scene', message = ('Reload Current Scene?\n'), button = ['Cancel','OK'], defaultButton = 'OK', cancelButton = 'Cancel', dismissString = 'Cancel' )
curFileLoc = cmds.file(query = True, location = True)
cmds.file( curFileLoc , force = True, open = True)
print "Re-Opening current file - ", curFileLoc
def main():
unlockRenderer(renderer="mayaHardware2")
saveFile()
if cmds.window("unifiedRenderGlobalsWindow", exists=True):
cmds.deleteUI("unifiedRenderGlobalsWindow")
mel.eval('resetAE()')
mel.eval('buildNewSceneUI;')
reloadScene()
main()
Something to note - At times, some errors such as #// Error: file: /apps/Linux64/aw/maya2014/scripts/others/unifiedRenderGlobalsWindow.mel line 1074: setParent: Object 'unifiedRenderGlobalsWindow' not found. // is still encountered, even after the file is reopened. It may differs accordingly to scene file
Related
I have the following code to enable the file browser using blender:
import bpy
import os
from bpy.props import StringProperty
from bpy_extras.io_utils import ImportHelper
from bpy.types import Operator
sel = ''
class OpenBrowser(bpy.types.Operator):
bl_idname = "open.file"
bl_label = "Select Excel File"
bli_description = "Simulation output excel file"
filter_glob: StringProperty(default = '*.xls;*.xlsx',options = {'HIDDEN'})
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
#somewhere to remember the address of the file
def execute(self, context):
global sel
sel = self.filepath
#self.selected_file = self.filepath
#display = "filepath= "+self.filepath
#print(display) #Prints to console
#Window>>>Toggle systen console
return {'FINISHED'}
def invoke(self, context, event): # See comments at end [1]
context.window_manager.fileselect_add(self)
global sel
sel = self.filepath
#Open browser, take reference to 'self'
#read the path to selected file,
#put path in declared string type data structure self.filepath
return {'RUNNING_MODAL'}
# Tells Blender to hang on for the slow user input
bpy.utils.register_class(OpenBrowser)
#Tell Blender this exists and should be used
# [1] In this invoke(self, context, event) is being triggered by the below command
#but in your script you create a button or menu item. When it is clicked
# Blender runs invoke() automatically.
#execute(self,context) prints self.filepath as proof it works.. I hope.
bpy.ops.open.file('INVOKE_DEFAULT')
print(sel)
The issue I am facing is that I have declared a global variable sel to which I want to save the filepath selected from the user when running the code. However, when I run the script I see that sel has not changed and it is as it was initialized. Could someone please help me on how to access from the class the self.filepath variable? What am I doing wrong here?
If I understand correctly, you want to store that value for later.
I'm not sure why 'sel' doesn't even update in your case, but I think the more correct way would be to use a property like so:
import bpy
# Assign a custom property to an existing type.
bpy.types.Scene.my_sel_value = bpy.props.StringProperty(name="Sel")
# Set property value.
bpy.context.scene.my_sel_value = "Foo"
# Get property value.
print(bpy.context.scene.my_sel_value)
Properties can be added to all ID types, but for "global" values, bpy.types.scene us ussualy used. Though there can be multiple scenes in one project and they will have separate values. Property values are stored when Blender closes.
If you are making an addon, you can also store your value in Addon Preferences. This value will be the same for all blender projects.
OK. So I have been running into this roadblock where I cant get the GUI to update based on what I am doing. I've searched extensively and tried to read but I am at my wits end almost. The closest Ive gotten is to remove the item from the "myclass.uncorrex_thing" and then run "edit_traits", but that just creates a new GUI over the old one...
Summary:
I am getting a list of filenames from a .csv that has alot of items that change daily. I just want to be able to select the filename from a list on the GUI, press a button that does something to the file and checks that filename off the .csv list, then have the dropdown list on the GUI updated with the updated .csv
Here is my code so far
class My_List(HasTraits):
tracker = RecordKeeping()
uncorrex_items = tracker.get_uncorrected_list() #this creates a list of filenames based on a .csv file
uncorrex_items.insert(0,'Select file')
class DataFrameEditorDemo(HasTraits):
err_correct = PostProcessAutoErrorCorrection() #a separate module for correcting the files
myclass = Instance(My_List)
highlighted_thing = Str
Calc = Button('Run Corrections')
traits_view = View(
Item('Calc', label='correct file'),
Item("highlighted_thing", editor= EnumEditor(name = 'object.myclass.uncorrex_items')),
title="MyEditor"
)
def _Calc_fired(self):
if len(self.highlighted_thing) == 8:
self.err_correct.correct_form(self.highlighted_thing) #this corrects the file selected from the dropdown list
#AND it updates the .csv file so the file should be checked as complete and will not show up when "tracker.get_uncorrected_list()" is run again
OK, for anyone looking at this and wondering, I finally solved my issue. Basically had to create a property class which depends on an event (button press). When the button is pressed the highlighted_thing updates and the function which corrects the form and updates the .csv is run
class DataFrameEditorDemo(HasTraits):
err_correct = PostProcessAutoErrorCorrection() #a separate module for correcting the files
tracker = RecordKeeping() #a separate module for managing the .csv
highlighted_thing = Property(List, depends_on = 'Calc')
test = Str
Calc = Button('Run Corrections')
traits_view = View(
Item('Calc', label='correct file'),
Item("test", editor= EnumEditor(name = 'highlighted_thing')),
title="MyEditor"
)
def _get_highlighted_thing(self):
return tracker.get_uncorrected_list()
def _Calc_fired(self):
if len(self.test) == 8:
self.err_correct.correct_form(self.test)
I've been following This Tutorial on using a .UI file from QT designer in a Maya plugin. It states that, in order to query the value of a QtextEdit field after the UI has been loaded into Maya, I need to do the following:
So now when we load our QT Ui inside of maya we can query the text of
our line edit every time we want to by using the following line of
code:
pm.textField('textFieldName', query = True, text = True)
However I can't seem to get this to function. I'm loading the UI as follows:
# Load our window and put it into a variable.
ebWin = cmds.loadUI(uiFile = self.BE_UIpath)
No issues there, when I try cmds.showWindow(ebWin), everything works and looks exactly as intended. Now, when I try to query the QtextEdit I've named 'exportDirectoryTF', Maya insists it does not exist. I've tried two different approaches:
approach A:
# Connect Functions to the buttons.
exportDir = ebWin.textField('exportDirectoryTF', query = True, text = True)
which outputs:
# Error: 'unicode' object has no attribute 'textField'
# # Traceback (most recent call last):
# # File "C:/Users/Censored/Documents/maya/2018/plug-ins/EB_pi_cmds.py", line 39, in doIt
# # exportDir = ebWin.textField('exportDirectoryTF', query = True, text = True)
# # AttributeError: 'unicode' object has no attribute 'textField'
and approach B:
import maya.cmds as cmds
# Connect Functions to the buttons.
exportDir = cmds.textField('exportDirectoryTF', query = True, text = True)
which returns:
# RuntimeError: Object 'exportDirectoryTF' not found.
# # Traceback (most recent call last):
# # File "C:/Users/Censored/Documents/maya/2018/plug-ins/EB_pi_cmds.py", line 39, in doIt
# # exportDir = cmds.textField('exportDirectoryTF', query = True, text = True)
# # RuntimeError: Object 'exportDirectoryTF' not found. #
The tutorial has 'pm.textField('textFieldName', q = True, text = True)', and I can't figure out where the "pm" came from, if it is supposed to indicate the variable from loading the UI or the maya Python textField command, or neither.
If anyone could point me in the right direction here, it would be greatly appreciated.
From your code it is not visible at which time you try to execute the textField cmd. This code below works fine for me. The test.ui only contains a widget with a lineEdit field called "lineEdit". Querying the text field only works if the window is visible. If you close the window and try to query the text field, you get the "object not found" error.
ui = "D:/temp/test.ui"
qtW = cmds.loadUI(uiFile = ui)
cmds.showWindow(qtW)
cmds.textField("lineEdit", query=True, text=True)
I am building a GUI using wxribbon of wxpython. The wxribbon is dynamic and user can add pages and panels. When user closes the ribbon, I am saving names and number of pages and panels in a json file before destroying the ribbon. On restoring the state, I read from json file and recreate my ribbon state, but when user want to now make changes to ribbon panel, only the last recreated panel works and for all the panels before the last one, I get following error :
**self.Bind(wx.EVT_MENU, lambda event: self.RemoveGroupBox(event, panel), RemoveGroupBox)
File "C:/Users/Samyak/Desktop/Japan_SRC/test/src/GUI/Trial Ribbon.py", line 327, in RemoveGroupBox
for child in newpanel.GetChildren():
File "C:\Python27\lib\site-packages\wx-2.8-msw-unicode\wx\_core.py", line 14619, in __getattr__
raise PyDeadObjectError(self.attrStr % self._name)
wx._core.PyDeadObjectError: The C++ part of the RibbonPanel object has been deleted, attribute access no longer allowed.**
The code I am using to restore my ribbon state is as follows: Please help me... Thanks a lot
if os.path.exists(CONFIGFILE):
with open(CONFIGFILE, 'r') as f:
data = json.load(f)
self.newpanel = []
for Page in data['pages']:
label = Page['label']
name = Page['name']
newpage = RB.RibbonPage(self._ribbon,wx.ID_ANY, Page['label'],Bitmap("eye.xpm"))
for panels in Page['Panel']:
pagelabel = panels['labelpanel']
self.newpanel.append(RB.RibbonPanel(newpage,wx.ID_ANY,pagelabel,Bitmap("selection_panel.xpm")))
length = len(self.newpanel)
self.newpanel[length-1].Bind(wx.EVT_RIGHT_UP, lambda event: self.RightClickRibbonPageBox(event, self.newpanel[length-1]))
currentpage = data['activepage']
self._ribbon.SetActivePage(currentpage)
self._ribbon.Realize()
I have found the error myself after trying for a long time. I am sorry for not providing the entire code as it was really big. The problem I was having was that I was not checking the condition of
"if isinstance(child, RB.RibbonPanel):".
while recreating ribbon from json file.After using it everything works fine.
I've to build a form in QGIS to customize data input for each polygon in the shapefile.
I use QtDesigner to create a form (.ui), with some textboxes and comboboxes pointing to the fields of my shapefile.
Then I use the python file from Nathan QGIS Blog to add some logic.
Python code:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
nameField = None
myDialog = None
def formOpen(dialog,layerid,featureid):
global myDialog
myDialog = dialog
global nameField
nameField = dialog.findChild(QTextEdit,"PART")
buttonBox = dialog.findChild(QDialogButtonBox,"buttonBox")
nameField.textChanged.connect(Name_onTextChanged)
# Disconnect the signal that QGIS has wired up for the dialog to the button box.
buttonBox.accepted.disconnect(myDialog.accept)
# Wire up our own signals.
buttonBox.accepted.connect(validate)
buttonBox.rejected.connect(myDialog.reject)
def validate():
# Make sure that the name field isn't empty.
if not nameField.text().length() > 0:
nameField.setStyleSheet("background-color: rgba(255, 107, 107, 150);")
msgBox = QMessageBox()
msgBox.setText("Field PART must not be NULL.")
msgBox.exec_()
else:
# Return the form as accpeted to QGIS.
myDialog.accept()
def Name_onTextChanged(text):
if not nameField.text().length() > 0:
nameField.setStyleSheet("background-color: rgba(255, 107, 107, 150);")
else:
nameField.setStyleSheet("")
So I open an edit session in QGIS and I click on a polygon with Identify tool, but when I clik on OK button on my customized form, regardless field PART is NULL or not, the following error occurs:
ERROR CODE LINE >>>> if not nameField.text().length() > 0:
ERROR MESSAGE >>>> AttributeError: 'str' object has no attribute 'text'
I'm running QGIS 1.7.4, Python 2.7.2, Windows 7 64-bit.
I miss something... Please, anybody can help me?
It looks like you have a Python error more than a problem with QGIS.
You have two instances of if not nameField.text().length() > 0:
def validate():
if not nameField.text().length() > 0:
and
def Name_onTextChanged(text):
if not nameField.text().length() > 0:
Initially, it looks like nameField is not an input for either of these functions. So I guess these are assigned somewhere else and you've reduced the code example. Also, you have text as a variable input for 'Name_onTextChanged' but you also try and use it as a function 'nameField.text().length()'. This might be a problem.
Generally, Python is complaining because it cannot perform the operation 'text()' on the variable nameField, which it believes is a string. There is no text() function available for strings. And it looks like nameField is actually supposed to be a QTextEdit object.
If nameField is a QTextEdit object, then you can use toPlainText() instead which should do what you need it to do. So something like
if not nameField.toPlainText().strip().length() > 0:
In this instance, I have included .strip() as well so that you do not get a positive result if there are white spaces in text field.
Does that help at all?