Maya: Import the same FBX file multiple times using Python - python

I've made a button in Maya that imports an .fbx file when pressed. When I press the button again to import the same .fbx it overwrites the one already in the scene, when the goal is to make a duplicate.
Example of what I'm trying to achieve: I press the button and it imports "sphere.fbx" into the scene as "sphere". I press the button again and it imports "sphere.fbx" into the scene as "sphere1".
This is all I'm using to import the .fbx:
cmds.file(shapePath + shapeList[value], i = True, mnc = True, ns = ":")
I've tried looking around for some solutions but I've had no luck.

Turns out you can't import the fbx file twice from what I can tell. What you can do as a workaround:
Attempt to import file
If it doesn't work, import the fbx file in as a reference
Make that reference part of the scene.
# Attempt to import fbx into the scene
# returnNewNodes(rnn) flag will tell us if it added anything
new_nodes = cmds.file(file_path, i=True, rnn=True)
print("Nodes added: {}".format(new_nodes))
# If nothing was added to the scene, import as reference
if not new_nodes:
cmds.file(file_path, mnc=True, reference=True)
# Make reference part of the scene
cmds.file(file_path, importReference=True)

Related

Python Win32API SendMessage win32con WM_SETTEXT only works once

Simplified and working code below, but only works once then not again until the window is restarted. Is there some sort of finish set text missing or some other limitation? Can't find any results on google, Thanks
import win32api
import win32gui
import win32con
handle = windowName #Script is working with actual window name
mainWindowHWND = win32gui.FindWindow(None, handle)
win32api.SendMessage(mainWindowHWND, win32con.WM_SETTEXT, 0, "test")
You need to find the exact control handle in order to send the text. Now, you are changing the window title of that program. So Assume that you are setting a notepad window's title to 'test'. Then it become a window with title 'test'. So you can't get the window handle again with the old text.
You need to enumerate the all the child windows of that specific window and check the type of control you are interested in. Then set the text of that control You can use EnumChildWindows api function for that.
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumchildwindows

Tkinter Cannot Find Image when it is in the same folder

I am trying to learn how to add images to tkinter (using a lot of youtube codemy videos). I have a kingdom management game I have been writing where I have been able to successfully add images as labels and as buttons and have them update as you progress through seasons of time in game.
However, when I started a new py file to work on a separate part of the code, suddenly Pycharm could not find any of the images and I got a:
"tkinter.TclError: couldn't open "summer.png": no such file or directory".
So, I copied my code that worked in the main instance in a separate py file and it still does not work and I get the same error. So, for whatever reason, in one file the same code is able to be used and it finds the png but in a second instance (with the "same" code) it cannot. Also, hovering over the image path allows me to see the image in Pycharm so I know it is still there (the images are in the same folder as my python project). I am wondering if there is something simple I am not seeing. All the below image paths work in my main program but it fails when I attempt to replicate it.
from tkinter import *
import pickle
import random
from pathlib import Path
root = Tk()
root.title("The Crumbling Kingdom")
root.geometry("1300x800")
bgsummer = PhotoImage(file="summer.png")
worldmap = PhotoImage(file="map1.png")
bgspring = PhotoImage(file="spring.png")
bgwinter = PhotoImage(file="winter.png")
bgfall = PhotoImage(file="fall.png")
worldmap = PhotoImage(file="map1.png")
table = PhotoImage(file="table.png")
side = PhotoImage(file="side.png")
backgroundimage = bgspring
my_background=Label(root, image= backgroundimage)
my_background.place(x=0,y=0, relwidth = 1, relheight =1)

Can't initialize turtle in Maya through scripting

I have a maya python tool that is supposed to load turtle, set it as the renderer, and then bake vertex AO on the selected object. The whole thing works except that when the user first opens Maya, it won't actually initialize the first time. It doesn't create the "TurtleDefaultBakeLayer" node for the script to modify attributes on. The user has to manually open the render settings window and then click on the "TURTLE" tab next to the "Common" tab for it to bake anything. After that it works exactly how it should with or without that Render Settings window open.
My question is, how do I get a freshly opened maya to get Turtle to initialize and instantiate those components without the user needing to open the Render Settings window?
def initializeTurtle(self):
#Load Turtle
cmds.loadPlugin('Turtle')
#Set renderer
cmds.setAttr("defaultRenderGlobals.currentRenderer", "turtle", type="string")
For anyone that was curious about solving this problem without opening the render settings window, the only viable solution we could come up with was to manually create the nodes Turtle needed, instead of relying on its automatic instantiation.
def initializeTurtle(self):
#Load Turtle
pluginStatus = cmds.pluginInfo( "Turtle", q = True, l = True, n = True )
if pluginStatus == False:
cmds.loadPlugin( "Turtle")
#Create bake nodes
cmds.setAttr("defaultRenderGlobals.currentRenderer", "turtle", type="string")
tOptions = cmds.createNode ("ilrOptionsNode", name="TurtleRenderOptions")
tBakeLayer = cmds.createNode ("ilrBakeLayer", name="TurtleDefaultBakeLayer")
tbakeLayerMgr = cmds.createNode ("ilrBakeLayerManager", name="TurtleBakeLayerManager")
cmds.connectAttr(tOptions+".message", tBakeLayer+".renderOptions")
cmds.connectAttr(tBakeLayer+".index", tbakeLayerMgr+".bakeLayerId[0]")

First time loading a window in new scene, it opens two

I have this code.....
import sys
sys.path.insert(0, '...')
import rotTool
reload(rotTool)
rotTool()
First time loading it into maya I get two windows. I realize it's because of the reload there, but without it, it won't load if you closed the window and need to reopen (while in the same session). How best should I fix this?
Thanks in advance
Let's say inside rotTool.py it looks something like this:
from PySide import QtGui
class RotTool(QtGui.QWidget):
def __init__(self, parent = None):
super(RotTool, self).__init__(parent)
self.resize(400, 400)
def run(self):
self.show()
It's a class that inherits from a QWidget, and when you call the run function, it opens up a window and shows it. Maybe you're not using PySide but the same idea should apply.
In Maya, if I need to open this window I execute:
import rotTool # Import module
myWin = rotTool.RotTool() # Create an instance of the class
myWin.run() # Call the instance's run method to open it up
If I close the window, I can just execute the last 2 lines again to create a new instance that opens the window. There could be a bit more to it than that, like making sure 2 windows can't be open at the same time, but this is how I would generally go about it.
I'm not sure what's in your module so it's hard to give specific advice to it. Instead of opening your window at the bottom of your script, you might just need to wrap it around a function, like my run() example, so that it doesn't automatically open on an import or reload. Hope that helps!

SVG interaction in python with cairo, opengl and rsvg

I render a huge SVG file with a lot of elements with Cairo, OpenGL and rsvg. I draw svg on cairo surface via rsvg and create an OpenGL texture to draw it. Everything is fine. And now I have to interact with elements from SVG. For example, I want to guess an element by coordinates. And I want to change the background of some path in SVG. In the case of changing background I think, I can change SVG DOM and somehow re-render a part of SVG. But in the case of hit testing elements I'm totally embarrassed.
So, is there some python library to interact with SVG? Is it possible to stay with cairo and rsvg and how can I implement it myself? Or is there a better way to render SVG in OpenGL and interact with it in python? All I want is load SVG, manipulate its DOM and render it
I don't know much about librsvg, but it does not appear to have been updated since 2005, and so I would be inclined to recommend using a different implementation.
If you don't have dependencies on any Python libraries outside of the standard library, then you could use Jython together with Batik. This allows you to add event handlers, as well as change the DOM after rendering.
For an example of how to do this with Java, see this link.
Here's a quick port to Jython 2.2.1 (runs, but not thoroughly tested):
from java.awt.event import WindowAdapter;
from java.awt.event import WindowEvent;
from javax.swing import JFrame;
from org.apache.batik.swing import JSVGCanvas;
from org.apache.batik.swing.svg import SVGLoadEventDispatcherAdapter;
from org.apache.batik.swing.svg import SVGLoadEventDispatcherEvent;
from org.apache.batik.script import Window;
from org.w3c.dom import Document;
from org.w3c.dom import Element;
from org.w3c.dom.events import Event;
from org.w3c.dom.events import EventListener;
from org.w3c.dom.events import EventTarget;
class SVGApplication :
def __init__(self) :
class MySVGLoadEventDispatcherAdapter(SVGLoadEventDispatcherAdapter):
def svgLoadEventDispatcherListener(e):
# At this time the document is available...
self.document = self.canvas.getSVGDocument();
# ...and the window object too.
self.window = self.canvas.getUpdateManager().getScriptingEnvironment().createWindow();
# Registers the listeners on the document
# just before the SVGLoad event is
# dispatched.
registerListeners();
# It is time to pack the frame.
self.frame.pack();
def windowAdapter(e):
# The canvas is ready to load the base document
# now, from the AWT thread.
self.canvas.setURI("doc.svg");
self.frame = JFrame(windowOpened = windowAdapter, size=(800, 600));
self.canvas = JSVGCanvas();
# Forces the canvas to always be dynamic even if the current
# document does not contain scripting or animation.
self.canvas.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC);
self.canvas.addSVGLoadEventDispatcherListener(MySVGLoadEventDispatcherAdapter()) ;
self.frame.getContentPane().add(self.canvas);
self.frame.show()
def registerListeners(self) :
# Gets an element from the loaded document.
elt = self.document.getElementById("elt-id");
t = elt;
def eventHandler(e):
print e, type(e)
self.window.setTimeout(500,run = lambda : self.window.alert("Delayed Action invoked!"));
#window.setInterval(Animation(), 50);
# Adds a 'onload' listener
t.addEventListener("SVGLoad", false, handleEvent = eventHandler );
# Adds a 'onclick' listener
t.addEventListener("click", false, handleEvent = eventHandler );
if __name__ == "__main__":
SVGApplication();
Run with:
jython -Dpython.path=/usr/share/java/batik-all.jar:/home/jacob/apps/batik-1.7/lib/xml-apis-ext.jar test.py
An alternative approach would be is to use blender. It supports svg import and interaction using python. I don't think it will allow you to edit the dom after import.
I had to do the same (changing element color for instance), and had to modify rsvg library because all those nice features exist but they are hidden. You have to make a new interface to link to the nice features.

Categories