I'm trying to create a function that creates emitters (emitting from objects), but I'm having trouble getting it to work with multiple objects at the same time.
I want emitter1 to be connected to nParticle1 and emitter2 to nParticle2.
def particalWebSystem(webDensity,genoration):
selectedObject = cmds.ls( selection = True )
print selectedObject
if len(selectedObject)==0:
cmds.confirmDialog( title='Warning', message='Please select at least one object', button=['Close'], defaultButton='Close', cancelButton='Close', dismissString='Close' )
if len(selectedObject)==1:
print "<2"
else:
print ">2"
emitting = cmds.emitter( selectedObject, n='emitter' )
cmds.particle( n = 'nParticle#' )
cmds.connectDynamic( 'nParticle#', em = 'emitter' )
cmds.setAttr( "emitter.emitterType", 2 )
cmds.setAttr( "nParticle#Shape.lifespanMode", 2 )
cmds.setAttr( "nParticle#Shape.maxCount", webDensity )
cmds.setAttr( "nParticle#Shape.lifespanRandom", generation )
You can simplify this problem by making sure you use the name of the emitter you actually create -- you never know what name you'll really get because Maya will rename things. It's best to always capture the names of things you create and work on them instead of hoping you get the names you asked for.
This version makes a function and just calls it on every selected object. It will silently do nothing for empty selections it also returns the objects created in case you need them later.
import maya.cmds as cmds
def setup_emitter(source_object, maxcount, life_random):
source_object, emitting = cmds.emitter( source_object, n=source_object + "_emitter" )
particle, particleshape = cmds.particle( n = source_object + "_particles" )
cmds.connectDynamic( particle, em = emitting)
cmds.setAttr( emitting + ".emitterType", 2 )
cmds.setAttr( particleshape + ".lifespanMode", 2 )
cmds.setAttr( particleshape + ".maxCount", maxcount )
cmds.setAttr( particleshape + ".lifespanRandom", life_random )
return emitting, particleshape
for selection in cmds.ls(sl=True, type='transform'):
print setup_emitter(selection, 100, 100) # your values here
Related
Working on some code that uses pysimplegui as the UI and SQlite for the data sorting. I'm using SQLite's execute function to select data based on input from the user in the UI through variables. For example user wants to search for part name they input all or part of the name into the box, hit the search button which then runs my "parts_search" method, which will then only filter the result based on part name. OR the user enters information in multiple boxes which then filters based on the boxes that have information.
This here is runnable code provided you add a file base1.db in the same folder location as the script itself
import PySimpleGUI as sg
import os.path
import sqlite3
# sql var
c = None
conn = None
setup = None
# list var
parts = []
def sql():
global setup
conn_sql()
c.execute("""CREATE TABLE IF NOT EXISTS parts (part_name TEXT, part_number TEXT, part_series TEXT,
part_size INTEGER, job_type TEXT)""")
conn.commit()
if conn:
conn.close()
def conn_sql():
global c
global conn
# SQL connection var
if os.path.isfile('./base1.db'):
conn = sqlite3.connect('base1.db')
c = conn.cursor()
def main_gui_parts():
global parts
layout = [[sg.Text('Part Name: '), sg.Input(size=(20, 1), key='-PName-'), sg.Text('Part Series:'),
sg.Input(size=(10, 1), key='-PSeries-')],
[sg.Text('Part Number:'), sg.Input(size=(20, 1), key='-PNumber-'), sg.Text('Part Size:'),
sg.Input(size=(10, 1), key='-PSize-')],
[sg.Checkbox('Fit', key='-PFit-'), sg.Checkbox('Weld', key='-PWeld-'),
sg.Checkbox('Assemble', key='-PAssemble-'),
sg.Button('Search', key='-PSearch-')],
[sg.Listbox(parts, size=(58, 10), key='-PParts-')], [sg.Button('Back', key='-PBack-')]]
window = sg.Window('parts list', layout, grab_anywhere=True)
sql()
while True:
event, values = window.read()
if event == 'Close' or event == sg.WIN_CLOSED:
break
# PART WINDOW
part_name = values['-PName-']
part_series = values['-PSeries-']
part_number = values['-PNumber-']
part_size = values['-PSize-']
fit = values['-PFit-']
weld = values['-PWeld-']
assemble = values['-PAssemble-']
if event == '-PSearch-':
print('search parts')
part_search(part_name, part_series, part_number, part_size, fit, weld, assemble)
if event == '-PBack-':
break
window.close()
def part_search(part_name, part_series, part_number, part_size, fit, weld, assemble):
global parts
conn_sql()
filter_original = """SELECT * FROM parts WHERE """
filter = filter_original
if part_name:
print('part name: ' + part_name)
if filter == filter_original:
filter += """part_name LIKE ? """
else:
filter += """AND part_name LIKE ? """
if part_series:
print('part series: ' + part_series)
if filter == filter_original:
filter += """part_series=(?) """
else:
filter += """AND part_series=(?) """
if part_number:
print('part number: ' + part_number)
if filter == filter_original:
filter += """part_number LIKE ? """ ### DONT USE LIKE???
else:
filter += """AND part_number LIKE ? """ ### DONT USE LIKE???
if part_size:
print('part size: ' + part_size)
if filter == filter_original:
filter += """part_size=(?) """
else:
filter += """AND part_size=(?) """
if fit:
print('job type: ' + str(fit))
if filter == filter_original:
filter += """job_type = fit """
else:
filter += """AND job_type = fit """
if weld:
print('job type: ' + str(weld))
if filter == filter_original:
filter += """job_type = weld """
else:
filter += """AND job_type = weld """
if assemble:
print('job type: ' + str(assemble))
if filter == filter_original:
filter += """job_type = assemble"""
else:
filter += """AND job_type = assemble"""
print(filter)
#if filter != filter_original:
#c.execute(filter, ())
#else:
#c.execute("""SELECT * FROM parts""")
main_gui_parts()
THE PROBLEM: The commented code at the bottom is where I'm having trouble figuring out (in the "part_search" method). I don't use all of the variables all the time. Only filter with the variables provided by the user. which means the tuple should only have the variables which was input by the user.
If all the variables were used this is what it would look like. c.execute(filter, (part_name, part_series, part_number, part_size, fit, weld, assemble)) but more often than not only some of those variable will have been used and may need to look like this instead. c.execute(filter, (part_name, part_series, weld)) Somehow I need the variables here to be removeable(for lack of better word)
I've been learning a lot about SQLite but I could be seeing tunnel vision and can't think of a different way to go about this.
Probably the easiest way to deal with this is to put all the filter conditions and values into lists, and then only add a WHERE clause if the length of the filters list is non-zero. For example:
query = """SELECT * FROM parts"""
filters = []
values = []
if part_name:
filters.append("""part_name LIKE ?""")
values.append(part_name)
...
if len(filters):
query += ' WHERE ' + ' AND '.join(filters)
c.execute(query, tuple(values))
Note: should your filters ever include OR conditions, you need to parenthesise them when building the query to ensure correct operation i.e.
query += ' WHERE (' + ') AND ('.join(filters) + ')'
order = 2
selected = 0
while selected < 21: # because I can only select 20 rows the most once.
current_tr = driver.find_element_by_xpath('/ html / body / table / tbody / tr / td / div / div[3] / table / tbody / tr[%d]' % order) # form line 1. below the table's header
if current_tr.get_attribute("bgcolor") is None: # no bgcolor means not yet reviewed
driver.find_element_by_xpath("//td[2]/div/a").click() # check the onclick content
div_content = driver.find_element_by_xpath("//td[2]/div/div").text # fetch onclick content
driver.find_element_by_xpath("//td[2]/div/div/a").click() # close the onclick content
print(div_content)
if "car" in div_content: #judge if certain string exists in onclick content
list_content = div_content.split("【car】")
car_close = list_content[1].strip() # fetch the content
list_car = car_close.split(" ")
car = list_doi[0]
print(car)
orderminus = order - 1
driver.find_element_by_xpath('// *[ # id = "%d"] / td[6] / a' % orderminus).click() # pick this row,
time.sleep(1)
selected = selected + 1
order = order + 0 #if this row is picked, the row will disappear, so the order won't change
else: ###problem is here, the else branch seems like never been executed ? otherwise the if always stands? no, not possible. there are ones exclude "car", the problem occurs at the first instance of div_content without "car"
order = order + 1 # if "car" is not in
time.sleep(1)
else: # if already reviewed, order + 1
order = order + 1
above is my code using selenium to navigate the webpage with a table.
First judgement: if the current row is reviewed,
not yet reviewed? ok, print the info;
already reviewed?skip it.
then plus judgement: if there certain string "car" in the info:
no? skip;
yes, click it, the row disappear;
But currently when I am running this, the actual status is :
when doing the plus judement, if the string "car" is not in the info,
it keeps printing the info, it seems it not doing the else branch, is doing the line 6_9 in this snippet, always, dead end loop.
Why? anybody give me a clue?
to make things clear, i have simplified my code as below:
list = []
list.append("ff122")
list.append("carff")
list.append("ff3232")
list.append("ffcar")
list.append("3232")
order = 0
selected = 0
while selected < 6:
current_tr = list[order]
print("round %d %s" % (order, current_tr))
if "ff" in current_tr:
print("ff is in current_tr")
if "car" in current_tr:
print("car")
selected = selected + 1
order = order + 0
else:
order = order + 1
print("order is %d" % order)
else: # if already reviewed, order + 1
order = order + 1
print("order is %d" % order)
everybody can run this, what I need to do is firstly filter the "ff", if "ff" exists, then filter "car". both two conditions TRUE, selected +1, until selected reach certain number. in real instance, don't doubt that the list is long enough.
The function below creates a nicely formatted list of all attributes of an OptionMenu widget. However a kludge is needed because OptionMenu does not having a "Menu size"' attribute (that holds the number of elements inside the dropdown list).
How do I extract this value from the widget so I can eliminate the kludge (and show the attributes of EVERY entry in the drop-down menu) ?
BTW, The function does not list the contents of the (non-standard) Optionmenu "command" option. For info on this option see the accepted answer to tkinter OptionMenu issue (bug?): GUI and program values not kept in lockstep (python 3.x) )
def OptionMenuConfigLister( OptionMenuWidget ) :
'''
Uncomment this block to see ALL attributes of the widget
#
# Gets the main attributes of the widget (EXCLUDING the attributes for
# the dropdown list and the values in the list)
#
print( " \nOptionMenuWidget.config()\n" )
for i, j in enumerate( sorted( OptionMenuWidget.config().items() ) ) :
print( " {0:<19} |{1}|".format( j[ 0 ], j[ 1 ][ -1 ] ), flush = True )
#
# Gets the attributes of the list portion of the widget (but NOT the entries)
#
print( "\nOptionMenuWidget[ 'menu' ].config().items() :\n" )
for i, j in enumerate( sorted( OptionMenuWidget[ 'menu' ].config().items() ) ) :
print( " {0:<18} |{1}|".format( j[ 0 ], j[ 1 ][ -1 ] ), flush = True )
'''
#
# Get the attributes of each/every entry in the dropdown list
#
# TODO: Determine how to get # of items in list
#
for i in range( 0, 1 ) : ''' <======== KLUDGE '''
print( "\nOptionMenuWidget[ 'menu' ].entryconfig(" + str( i ) + ").items()) :\n" )
for _, j in enumerate( sorted(
OptionMenuWidget[ 'menu' ].entryconfig( i ).items() ) ) :
print( " {0:<16} |{1}|".format( j[ 0 ], j[ 1 ][ -1 ] ), flush = True )
print()
return
EDIT 20180117: Here's the fix, based on the answer by #nae - replace the kludge line with:
ElementCount = OptionMenuWidget[ 'menu' ].index( 'end' ) + 1
for i in range( 0, ElementCount ) :
And as per comment by #furas, sample code now uses [ -1 ] in the formatted print statements.
Based on Menu total index counts and from the source code, the fact that OptionMenu's *values are stored as Menu items:
class OptionMenu(Menubutton):
"""OptionMenu which allows the user to select a value from a menu."""
def __init__(self, master, variable, value, *values, **kwargs):
...
menu.add_command(label=value,
command=_setit(variable, value, callback))
for v in values:
menu.add_command(label=v,
command=_setit(variable, v, callback))
self["menu"] = menu
One can extract the 'Menu Size' using .index('end') for OptionMenu's menu option like the following:
import tkinter as tk
root = tk.Tk()
opt_var = tk.IntVar()
opt = tk.OptionMenu(root, opt_var, 3, 2, 3, 5, 4)
opt.pack()
print(opt['menu'].index('end') + 1) # basically len(*values) + len(value)
root.mainloop()
Using a Korean Input Method Editor (IME), it's possible to type 버리 + 어 and it will automatically become 버려.
Is there a way to programmatically do that in Python?
>>> x, y = '버리', '어'
>>> z = '버려'
>>> ord(z[-1])
47140
>>> ord(x[-1]), ord(y)
(47532, 50612)
Is there a way to compute that 47532 + 50612 -> 47140?
Here's some more examples:
가보 + 아 -> 가봐
끝나 + ㄹ -> 끝날
I'm a Korean. First, if you type 버리 + 어, it becomes 버리어 not 버려. 버려 is an abbreviation of 버리어 and it's not automatically generated. Also 가보아 cannot becomes 가봐 automatically during typing by the same reason.
Second, by contrast, 끝나 + ㄹ becomes 끝날 because 나 has no jongseong(종성). Note that one character of Hangul is made of choseong(초성), jungseong(중성), and jongseong. choseong and jongseong are a consonant, jungseong is a vowel. See more at Wikipedia. So only when there's no jongseong during typing (like 끝나), there's a chance that it can have jongseong(ㄹ).
If you want to make 버리 + 어 to 버려, you should implement some Korean language grammar like, especially for this case, abbreviation of jungseong. For example ㅣ + ㅓ = ㅕ, ㅗ + ㅏ = ㅘ as you provided. 한글 맞춤법 chapter 4. section 5 (I can't find English pages right now) defines abbreviation like this. It's possible, but not so easy job especially for non-Koreans.
Next, if what you want is just to make 끝나 + ㄹ to 끝날, it can be a relatively easy job since there're libraries which can handle composition and decomposition of choseong, jungseong, jongseong. In case of Python, I found hgtk. You can try like this (nonpractical code):
# hgtk methods take one character at a time
cjj1 = hgtk.letter.decompose('나') # ('ㄴ', 'ㅏ', '')
cjj2 = hgtk.letter.decompose('ㄹ') # ('ㄹ', '', '')
if cjj1[2]) == '' and cjj2[1]) == '':
cjj = (cjj1[0], cjj1[1], cjj2[0])
cjj2 = None
Still, without proper knowledge of Hangul, it will be very hard to get it done.
You could use your own Translation table.
The drawback is you have to input all pairs manual or you have a file to get it from.
For instance:
# Sample Korean chars to map
k = [[('버리', '어'), ('버려')], [('가보', '아'), ('가봐')], [('끝나', 'ㄹ'), ('끝날')]]
class Korean(object):
def __init__(self):
self.map = {}
for m in k:
key = m[0][0] + m[0][1]
self.map[hash(key)] = m[1]
def __getitem__(self, item):
return self.map[hash(item)]
def translate(self, s):
return [ self.map[hash(token)] for token in s]
if __name__ == '__main__':
k_map = Korean()
k_chars = [ m[0][0] + m[0][1] for m in k]
print('Input: %s' % k_chars)
print('Output: %s' % k_map.translate(k_chars))
one_char_3 = k[0][0][0] + k[0][0][1]
print('%s = %s' % (one_char_3, k_map[ one_char_3 ]) )
Input: ['버리어', '가보아', '끝나ㄹ']
Output: ['버려', '가봐', '끝날']
버리어 = 버려
Tested with Python:3.4.2
The latest Python Sendkeys module is for Python 2.6. I can't upgrade it myself as it needs the C module to be recompiled.
Does anyone know of a fairly easy alternative way to send keys to a window?
Using win32ui.FindWindow() I can find the right window, then make it active with PyCWnd.SetActiveWindow(), so all that's needed is a simple way to send keystrokes to the active window.
The purpose is to execute a menu item.
The app was written in Delphi, and doesn't have any inter-process interface that I know about.
Here is a working module that calls user32.SendInput().
Not perfect, but usable.
Edit:
Yesterday I did a version with a class, and am using it in a working tkinter app. Will put it here when i get time to clean it up.
Have added this in the doc string below:
[ It is OK if I work from a folder within my profile.
These problems happened when working on another partition.
File permissions were OK, so do not know what blocked SendInput. ]
SciTE still needs the full exact window title.
#!/usr/bin/python
# -*- coding: utf-8 -*-
''' send_input for python 3, from jh45dev#gmail.com
code from Daniel F is adapted here. The original is at:
http://mail.python.org/pipermail/python-win32/2005-April/003131.html
SendInput sends to the window that has the keyboard focus.
That window must not be minimized.
There seem to be some strange limitations with user32.SendInput()
Here is what happened in my testing (on Vista sp2).
[edit: It is OK if I work from a folder within my profile.
These problems happened when working on another partition.
File permissions were OK, so do not know what blocked SendInput.]
1
I opened Notepad from the Start menu,
then in Notepad opened test.txt,
and all worked fine.
2
I opened Notepad by opening test.txt in Explorer.
find_window() found Notepad, but user32.SendInput() had no effect.
If Notepad was minimized, it did not get restored or focussed.
The same happened with SciTE and Notepad2.
Another strangeness:
For SciTE I had to put in the whole window title, eg "test.txt - SciTE",
but for Notepad and Notepad2, only the app name, eg "Notepad".
'''
import ctypes as ct
from win32con import SW_MINIMIZE, SW_RESTORE
from win32ui import FindWindow, error as ui_err
from time import sleep
class cls_KeyBdInput(ct.Structure):
_fields_ = [
("wVk", ct.c_ushort),
("wScan", ct.c_ushort),
("dwFlags", ct.c_ulong),
("time", ct.c_ulong),
("dwExtraInfo", ct.POINTER(ct.c_ulong) )
]
class cls_HardwareInput(ct.Structure):
_fields_ = [
("uMsg", ct.c_ulong),
("wParamL", ct.c_short),
("wParamH", ct.c_ushort)
]
class cls_MouseInput(ct.Structure):
_fields_ = [
("dx", ct.c_long),
("dy", ct.c_long),
("mouseData", ct.c_ulong),
("dwFlags", ct.c_ulong),
("time", ct.c_ulong),
("dwExtraInfo", ct.POINTER(ct.c_ulong) )
]
class cls_Input_I(ct.Union):
_fields_ = [
("ki", cls_KeyBdInput),
("mi", cls_MouseInput),
("hi", cls_HardwareInput)
]
class cls_Input(ct.Structure):
_fields_ = [
("type", ct.c_ulong),
("ii", cls_Input_I)
]
def find_window( s_app_name ):
try:
window1 = FindWindow( None, s_app_name,)
return window1
except ui_err:
pass
except:
raise
try:
window1 = FindWindow( s_app_name, None, )
return window1
except ui_err:
return None
except:
raise
def make_input_objects( l_keys ):
p_ExtraInfo_0 = ct.pointer(ct.c_ulong(0))
l_inputs = [ ]
for n_key, n_updown in l_keys:
ki = cls_KeyBdInput( n_key, 0, n_updown, 0, p_ExtraInfo_0 )
ii = cls_Input_I()
ii.ki = ki
l_inputs.append( ii )
n_inputs = len(l_inputs)
l_inputs_2=[]
for ndx in range( 0, n_inputs ):
s2 = "(1, l_inputs[%s])" % ndx
l_inputs_2.append(s2)
s_inputs = ', '.join(l_inputs_2)
cls_input_array = cls_Input * n_inputs
o_input_array = eval( "cls_input_array( %s )" % s_inputs )
p_input_array = ct.pointer( o_input_array )
n_size_0 = ct.sizeof( o_input_array[0] )
# these are the args for user32.SendInput()
return ( n_inputs, p_input_array, n_size_0 )
'''It is interesting that o_input_array has gone out of scope
by the time p_input_array is used, but it works.'''
def send_input( window1, t_inputs, b_minimize=True ):
tpl1 = window1.GetWindowPlacement()
was_min = False
if tpl1[1] == 2:
was_min = True
window1.ShowWindow(SW_RESTORE)
sleep(0.2)
window1.SetForegroundWindow()
sleep(0.2)
window1.SetFocus()
sleep(0.2)
rv = ct.windll.user32.SendInput( *t_inputs )
if was_min and b_minimize:
sleep(0.3) # if the last input was Save, it may need time to take effect
window1.ShowWindow(SW_MINIMIZE)
return rv
# define some commonly-used key sequences
t_ctrl_s = ( # save in many apps
( 0x11, 0 ),
( 0x53, 0 ),
( 0x11, 2 ),
)
t_ctrl_r = ( # reload in some apps
( 0x11, 0 ),
( 0x52, 0 ),
( 0x11, 2 ),
)
def test():
# file > open; a non-invasive way to test
t_ctrl_o = ( ( 0x11, 0 ), ( 0x4F, 0 ), ( 0x11, 2 ), )
# writes "Hello\n"
# 0x10 is shift. note that to repeat a key, as with 4C here, you have to release it after the first press
t_hello = ( ( 0x10, 0 ), ( 0x48, 0 ), ( 0x10, 2 ), ( 0x45, 0 ), ( 0x4C, 0 ), ( 0x4C, 2 ), ( 0x4C, 0 ), ( 0x4F, 0 ), ( 0x0D, 0 ), )
l_keys = [ ]
## l_keys.extend( t_ctrl_o )
l_keys.extend( t_hello )
l_keys.extend( t_ctrl_s )
## s_app_name = "SciTE"
## s_app_name = "(Untitled) - SciTE"
s_app_name = "test.txt - SciTE"
## s_app_name = "Notepad2"
## s_app_name = "Notepad"
window1 = find_window( s_app_name )
if window1 == None:
print( "%r has no window." % s_app_name )
input( 'press enter to close' )
exit()
t_inputs = make_input_objects( l_keys )
n = send_input( window1, t_inputs )
## print( "SendInput returned: %r" % n )
## print( "GetLastError: %r" % ct.windll.kernel32.GetLastError() )
## input( 'press enter to close' )
if __name__ == '__main__':
test()
I rewrote the C bits of sendkeys in ctypes a while ago...
https://bitbucket.org/markm/sendkeysctypes
and I see someone else did it too:
http://code.google.com/p/sendkeys-ctypes/
If I remember it should be a drop in replacement for sendkeys (only the import line has to change)
Got something that works, using win32api.keybd_event.
Looks like SendInput would be safer, but pywin32 does not include it.
[ edit: See a SendInput version in the accepted answer below. I leave this message here in case someone prefers to use sendkeys. jh ]
This page helped: http://social.msdn.microsoft.com/Search/en-us/?Query=keybd_event
Code that works:
import win32api;
import win32ui
PyCWnd1 = win32ui.FindWindow( None, "an_app" )
PyCWnd1.SetForegroundWindow()
PyCWnd1.SetFocus()
win32api.keybd_event(0x12, 0, ) # Alt
win32api.keybd_event(0x12, 0, 2 ) # Alt release
win32api.keybd_event(0x46, 0, ) # F
win32api.keybd_event(0x52, 0, ) # R
This does File > Reload in the app. Does not work if the app is minimized
Without releasing Alt, after running this, the keyboard behaved like i was holding the Alt key!
Don't seem to need to release the other keys
You want the keybd_event API. My PushKeys program is syntax compatible with SendKeys and has a sleep function built in. Although it isn't in Python it should be translatable readily enough (its been translated into a lot of languages - at least it should show you the API to use). It is available here in a variety of languages.