This question already has answers here:
Does "IndexError: list index out of range" when trying to access the N'th item mean that my list has less than N items?
(7 answers)
Closed 2 years ago.
first of all, sorry if this is already answered I've looked through past Q's but no luck.
My problem is: I've gone through the Python+libtcod tutorial on Roguebasin once and doing it again while making my own modifications.
I'm trying to make a hardcoded map instead of a randomly generated one.
The code so far will not show a window or anything I'm just running and hope it closes with no errors. BUT, I keep getting this:
Traceback (most recent call last):
File "superrogue.py", line 85, in <module>
make_map()
File "superrogue.py", line 68, in make_map
if MAP_FILE[x][y] in TILE_NAMES: #Find the tile's name---
IndexError: string index out of range
The whole "string index out of range" is what I've been beating my head against the wall all afternoon and evening.
Here's the code so far:
#---Imports-------------------------------------------------------------
import libtcodpy as libtcod
#---Program Labelings---------------------------------------------------
TITLE = 'Roguetest'
VERSION = '0.01a'
#---Setup Variables-----------------------------------------------------
SCREEN_WIDTH = 80
SCREEN_HEIGHT = 50
LIMIT_FPS = 20
#MAP_FILE = open('Maps/Test.txt', 'r')
#MAP_FILE = MAP_FILE.readlines()
MAP_FILE = ['XXXX',
'X==X',
'X..X',
'X..X',
'X==X',
'XXXX',
]
MAP_WIDTH = len(MAP_FILE[0])
print MAP_WIDTH
MAP_HEIGHT = len(MAP_FILE)
print MAP_HEIGHT
#---Dictionaries--------------------------------------------------------------
COLORS = {
'dark_new' : libtcod.Color(255, 0, 255),
'light_new' : libtcod.Color(255, 0, 255),
'dark_pavement' : libtcod.Color(20, 20, 20),
'light_pavement' : libtcod.Color(50, 50, 50),
'dark_sidewalk' : libtcod.Color(80, 80, 80),
'light_sidewalk' : libtcod.Color(120, 120, 120),
'dark_wall' : libtcod.Color(100, 100, 100),
'light_wall' : libtcod.Color(180, 180, 180)
}
TILE_NAMES = {
'X' : 'wall',
'.' : 'pavement',
'=' : 'sidewalk'
}
#---Classes-------------------------------------------------------------
class Tile:
def __init__(self, name):
self.name = name
self.darkcolor = COLORS['dark_' + self.name]
self.lightcolor = COLORS['light_' + self.name]
self.blocks = False
self.blocks_sight = False
self.inside = False
#---Functions-----------------------------------------------------------
def make_map():
map = [[ Tile(name='new')
for x in range(MAP_WIDTH) ]
for y in range(MAP_HEIGHT) ]
for x in range(MAP_WIDTH):
for y in range(MAP_HEIGHT):
print (x, y)
if MAP_FILE[x][y] in TILE_NAMES: #Find the tile's name---
map[x][y].name = TILE_NAMES[MAP_FILE[x][y]]
map[x][y].darkcolor = COLORS['dark_' + map[x][y].name]
map[x][y].lightcolor = COLORS['light_' + map[x][y].name]
if MAP_FILE[x][y] == 'X': #The WALL tile------------------
map[x][y].blocked = True
map[x][y].block_sight = True
elif MAP_FILE[x][y] == '.': #The PAVEMENT tile--------------
map[x][y].blocked = False
map[x][y].block_sight = False
elif MAP_FILE[x][y] == '=': #The SIDEWALK tile--------------
map[x][y].block_sight = False
map[x][y].ped_walkable = True
make_map()
Thanks.
y is getting up to len(MAP_HEIGHT) - 1 (because of the range call); MAP_HEIGHT = len(MAP_FILE); MAP_FILE is a list with six elements.
Thus y will take the values 0, 1, 2, 3, 4, 5. However, the string only has four values, so trying to access the fifth or sixth character will fail.
I think you've tangled map height and map width (it's indexed by [y][x] and you access it by [x][y]).
Related
I've viewed some questions regarding the same issue but none of them could help me. The problem is as it says, I'm unable to fit data into learning model.
This is the main file, which calls out the class regarding the data i use to fit in the model:
def main():
action = input(
"Choose an action:\n A - Create LinearSVC classifier\n B - Create Random Forest Classifier\n C - Create K Nearest Neighbor classifier\n -> ").upper()
loader = ImageLoader()
if action == "A":
lsvc = LinearSVC(random_state=0, tol=1e-5)
lsvc.fit(loader.hogArray(), loader.labelArray())
joblib.dump(lsvc, './LSVCmodel.pkl')
elif action == "B":
rfc = RandomForestClassifier(n_estimators=100)
rfc.fit(loader.hogArray(), loader.labelArray())
joblib.dump(rfc, './RFmodel.pkl')
elif action == "C":
knc = KNeighborsClassifier(n_neighbors=3)
knc.fit(loader.hogArray(), loader.labelArray())
joblib.dump(knc, './KNCmodel.pkl')
else:
print("That's not a valid answer")
main()
The same error occurs with all 3 models. The class that retrieves the data is written as following:
class ImageProcess:
def __init__(self, image, hog_data=None):
self.hog_data = hog_data
self.image = image
def hog_data_extractor(self):
self.hog_data = feature.hog(self.image) / 255.0
return self.hog_data
def normalize(self):
imageRead = cv2.resize(cv2.imread(self.image), (150, 150))
gaussImage = cv2.fastNlMeansDenoisingColored(imageRead, None, 10, 10, 7, 21)
self.image = cv2.Canny(gaussImage, 100, 200)
self.image = cv2.cvtColor(self.image, cv2.COLOR_GRAY2RGB)
self.image *= np.array((0, 0, 1), np.uint8)
return self.image
class ImageLoader:
def __init__(self):
self.sourcePath = "dataset/seg_train/"
self.labels = ['Buildings', 'Forest', 'Glacier', 'Mountain', 'Sea', 'Street']
self.x_train = []
self.y_train = []
def fillArray(self):
label_train = []
le = LabelEncoder()
run_time = time.time()
for scene in self.labels:
scene_path = os.path.join(self.sourcePath, scene.lower())
fileNumber = 0
scene_length = len([image for image in os.listdir(scene_path)])
for img in os.listdir(scene_path):
per = (file_number / scene_length)
arrow = '-' * int(round(per * 100) - 1) + '>'
spaces = ' ' * (100 - len(arrow))
sys.stdout.write(
"\rProgress: [{0}] {1}% -Ellapsed time: {2}".format(arrow + spaces, int(round(per * 100, 2)),
(int(time.time() - run_time))))
file_number += 1
img_path = os.path.join(scene_path, img)
process = ImageProcess(img_path)
self.x_train.append(process.hog_data_extractor())
label_train.append(str(scene_type))
self.y_train = le.fit_transform(label_train)
def hogArray(self):
return self.x_train
def labelArray(self):
return self.y_train
A side note: Previously I didn't have this ImageLoader class, and simply had the method fillArray() under main() on the previous code, and it didn't give back this error, all was working well. But due to some restrictions I have to follow I tried to transferred it into a class to be use in more other files.
Traceback (most recent call last):
File "main.py", line 35, in <module>
main()
File "main.py", line 19, in main
lsvc.fit(loader.hogArray(), loader.labelArray())
File "/home/filipe/Documents/NovaPasta/2019_20/LP_recuperacao/Trabalho_recuperacao/venv/lib/python3.6/site-packages/sklearn/svm/classes.py", line 229, in fit
accept_large_sparse=False)
File "/home/filipe/Documents/NovaPasta/2019_20/LP_recuperacao/Trabalho_recuperacao/venv/lib/python3.6/site-packages/sklearn/utils/validation.py", line 756, in check_X_y
estimator=estimator)
File "/home/filipe/Documents/NovaPasta/2019_20/LP_recuperacao/Trabalho_recuperacao/venv/lib/python3.6/site-packages/sklearn/utils/validation.py", line 552, in check_array
"if it contains a single sample.".format(array))
ValueError: Expected 2D array, got 1D array instead:
array=[].
Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.
I've tried reshaping as its recommended in the error but it retrieves("AttributeError: 'list' object has no attribute 'reshape'") and since I didn't needed this reshape before I assumed this wasn't the solution.
Sorry if its poor coding but I'm not that much of an expert(not even close) and the time period I had to do this was very short so I just focused on getting it to work properly.
You are not calling fillArray. so the lists are empty. Try doing it at end of init function.
array=[] in error shows this.
I wanted to try out some raycasting with Python in Maya using OpenMaya.MFnMesh.anyIntersection().
I just want to cast a ray from on object downwards and hit a plane, not go any further so I get only one raycasthit and get the translation values from the raycasthit.
I got the code from a video and made it a bit clearer to understand.
For the code to run properly in Maya you need an object that is higher in the Y-axis than a different one, preferably a polyPlane(for example: having a polySphere at position [0, 3, 0] and a polyPlane at position [0, 0, 0], select the polySphere and run the code)
import maya.OpenMaya as OpenMaya
import maya.cmds as cmds
def RayReposition(*args):
direction = (0.0, -1, 0)
sel = cmds.ls(sl = True)
fromPositionRay = cmds.xform(sel[0], query = True, translation = True)
selShape = cmds.listRelatives(shapes = True)
meshes = cmds.ls(geometry = True)
cmds.select(clear = True)
for x in meshes:
if x == selShape[0]:
continue
else:
OpenMaya.MGlobal.selectByName(x)
sList = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList(sList)
item = OpenMaya.MDagPath()
sList.getDagPath(0, item)
item.extendToShape()
fnMesh = OpenMaya.MFnMesh(item)
raySource = OpenMaya.MFloatPoint(fromPositionRay[0], fromPositionRay[1], fromPositionRay[2], 1.0)
rayDir = OpenMaya.MFloatVector(direction[0], direction[1], direction[2])
faceIds = None
triIds = None
idsSorted = False
testBothDirections = False
worldSpace = OpenMaya.MSpace.kWorld
maxParam = 999999
accelParams = None
sortHits = True
hitPoints = OpenMaya.MFloatPointArray()
hitRayParams = OpenMaya.MFloatArray()
hitFaces = OpenMaya.MIntArray()
hitTris = None
hitBarys1 = None
hitBarys2 = None
tolerance = 0.0001
hit = fnMesh.anyIntersection(raySource, rayDir, worldSpace, maxParam, testBothDirections, faceIds, triIds, idsSorted, accelParams, tolerance, hitPoints, hitRayParams, hitFaces, hitTris, hitBarys1, hitBarys2)
OpenMaya.MGlobal.clearSelectionList()
firstHit = (hitPoints[0].x, hitPoints[0].y, hitPoints[0].z)
print firstHit
RayReposition()
I expected to get the translation values from the raycasthit but I get the following error:
TypeError: in method 'MFnMesh_anyIntersection', argument 4 of type 'MIntArray const *'
Using the OpenMaya.MFnMesh.allIntersections() function instead works perfectly fine but I get every single hit from the raycast, but I only want the first hit.
Links to the OpenMaya.MFnMesh API:
link: https://help.autodesk.com/view/MAYAUL/2016/ENU/?guid=__py_ref_class_open_maya_1_1_m_fn_mesh_html
The main thing is that anyIntersection is looking for a single intersection it hits first, not multiple. So your out parameters are of the wrong types because they're arrays.
I would also avoid clearing or making new selections in your loop as it would just slow down performance by having to redraw the viewports every time.
Here's a working example that will create a locator on the first mesh it hits:
import maya.OpenMaya as OpenMaya
import maya.cmds as cmds
def RayReposition(*args):
direction = (0.0, -1, 0)
sel = cmds.ls(sl=True)
fromPositionRay = cmds.xform(sel[0], query=True, translation=True)
selShape = cmds.listRelatives(shapes=True)
meshes = cmds.ls(geometry=True)
for x in meshes:
if x == selShape[0]:
continue
else:
sList = OpenMaya.MSelectionList()
sList.add(x)
item = OpenMaya.MDagPath()
sList.getDagPath(0, item)
item.extendToShape()
fnMesh = OpenMaya.MFnMesh(item)
raySource = OpenMaya.MFloatPoint(fromPositionRay[0], fromPositionRay[1], fromPositionRay[2], 1.0)
rayDir = OpenMaya.MFloatVector(direction[0], direction[1], direction[2])
worldSpace = OpenMaya.MSpace.kWorld
maxParam = 999999
testBothDirections = False
faceIds = None
triIds = None
idsSorted = False
accelParams = None
sortHits = True
hitPoints = OpenMaya.MFloatPoint()
hitRayParams = None
hitFaces = None
hitTris = None
hitBarys1 = None
hitBarys2 = None
tolerance = 0.0001
hit = fnMesh.anyIntersection(
raySource, rayDir, faceIds, triIds, idsSorted, worldSpace, maxParam, testBothDirections, accelParams,
hitPoints, hitRayParams, hitFaces, hitTris, hitBarys1, hitBarys2, tolerance)
if hit:
firstHit = (hitPoints.x, hitPoints.y, hitPoints.z)
loc = cmds.spaceLocator()[0]
cmds.xform(loc, ws=True, t=firstHit)
print "Hit on {} at {}".format(x, firstHit)
break
RayReposition()
I find the c++ documentation a bit more clearer of what the method expects for parameters.
I'm trying to achieve the pattern below.
Got as far as doing the first line, then I have no clue how to code the rest of the pattern.
Here's what I've done so far:
#Timothy Shek
from graphics import*
#open Graph Window
def main():
win = GraphWin("Example",100,100)
x = 7
y = 7
radius = 5
while x<=30 :
centre = Point(x,y)
circle1 = Circle(centre,radius)
circle1.setFill("red")
circle1.draw(win)
x = x+10
while x>=35 and x<=65 :
centre = Point(x+5,y)
circle2 = Circle(centre,radius)
circle2.setFill("red")
circle2.draw(win)
x = x+10
print(x)
while x>=67:
centre = Point(x+10,y)
circle1 = Circle(centre,radius)
circle1.setFill("red")
circle1.draw(win)
x = x+10
main()
I got it guys, thanks
Heres the solution
#Timothy Shek
from graphics import*
#open Graph Window
def main():
win = GraphWin("Patch2" ,100,100)
for x in (5, 15, 25, 40,50,60,75,85,95):
for y in (5, 15, 25, 40,50,60,75,85,95):
c = Circle(Point(x+2,y), 5)
d = Circle(Point(x+2,y), 5)
c.draw(win)
d.draw(win)
c.setFill("Red")
d.setFill("Red")
if x==15 or x==50 or x== 85:
if y==15 or y==50 or y== 85:
c2 = Circle(Point(x+2,y),5)
c2.draw(win)
c2.setFill("White")
main()
While there is nothing wrong with your solution, this is a bit more performant
from graphics import *
def main():
win = GraphWin("Patch2" ,100,100)
coords = [5, 15, 25, 40, 50, 60, 75, 85, 95]
centers = set([coords[i] for i in range(1, len(coords), 3)])
for i in xrange(len(coords)):
for j in xrange(i+1):
x, y = (coords[i], coords[j])
c1 = Circle(Point(x+2,y), 5)
c2 = Circle(Point(y+2,x), 5)
c1.draw(win)
c2.draw(win)
if x in centers and y in centers:
c1.setFill("White")
c2.setFill("White")
else:
c1.setFill("Red")
c2.setFill("Red")
main()
Update: "Better" version
And since I got bored and I liked this problem (yes, I program when I'm bored) I made a fully parameter-ized version which you can do some fun stuff with, like.
Probably over your head :) But maybe you learn something from it, so I'm posting it.
from graphics import *
def drawPattern(scale):
# Inner method: Draw a square of circles given the top-left point
def drawSquare(win, xCoord, yCoord, squareSize=30, numCircles=3, scale=1, scaleCircles=False, outer_color="Red", inner_color="White"):
# Overwrite the default scaling
if scale > 1:
squareSize *= scale
if scaleCircles:
numCircles *= scale
radius = squareSize/(numCircles*2) # Divide by 2 since it's the radius
from math import sqrt, floor
centerDiff = (2*radius) * floor(sqrt(numCircles)) # Used for drawing off-color circles
# xrange uses an exclusive stop value, so go one value past to make inclusive
for x in xrange(radius, squareSize+radius, radius*2):
for y in xrange(squareSize-radius, x-radius, -radius*2):
c1 = Circle(Point(x+xCoord+2,y+yCoord), radius)
c2 = Circle(Point(y+yCoord+2,x+xCoord), radius)
c1.draw(win)
c2.draw(win)
if (centerDiff < x < squareSize - centerDiff) and (centerDiff < y < squareSize - centerDiff):
c1.setFill(inner_color)
c2.setFill(inner_color)
else:
c1.setFill(outer_color)
c2.setFill(outer_color)
win = GraphWin("Patch2 (x{})".format(scale), 100*scale,100*scale)
coords = [0, 35, 70]
for x in coords:
for y in coords:
drawSquare(win, x*scale, y*scale, scale=scale) # normal (boring) version
# drawSquare(win, x*scale, y*scale, scale=scale, scaleCircles=True, outer_color="Blue") # Picture version
def main():
drawPattern(3)
main()
I'm writing a roguelike with libtcodpy. It works, but when I run this listing: http://kooneiform.wordpress.com/2009/03/29/241/ at the bottom of the page is a full listing and a few others I've tried, I get errors such as this:
FYI I'm on Windows and do have the libtcodpy.py, SDL.dll, libtcod-mingw.dll files and they do work when following the tutorial that is most popular for libtcodpy.
For the listing above I receive this specific error:
$ python roguelike_practice2.py
Traceback (most recent call last):
File "roguelike_practice2.py", line 165, in <module>
draw()
File "roguelike_practice2.py", line 98, in draw
libtcod.console_set_foreground_color(0, libtcod.white)
AttributeError: 'module' object has no attribute 'console_set_foreground_color'
I also on that same program encounter the exact same issue with console_set_background_color, console_print_left. None work. All with the same error.
For other listings such as this one:
#!/usr/bin/python
###imports###
import os
import libtcodpy as libtcod
###utility functions###
def get_key(key):
if key.vk == libtcod.KEY_CHAR:
return chr(key.c)
else:
return key.vk
###global constants and variables###
window_width = 46
window_height = 20
first = True
fov_px = 9
fov_py = 10
fov_recompute = True
fov_map = None
fov_colors = {
'dark wall' : libtcod.Color(0, 0, 100),
'light wall' : libtcod.Color(130, 110, 50),
'dark ground' : libtcod.Color(50, 50, 150),
'light ground' : libtcod.Color(200, 180, 50)
}
fov_init = False
fov_radius = 4
do = {
'up' : (0, -1),
'down' : (0, 1),
'right' : (1, 0),
'left' : (-1, 0)
}
keys = {
'i' : do['up'],
'k' : do['down'],
'j' : do['left'],
'l' : do['right'],
libtcod.KEY_UP : do['up'],
libtcod.KEY_KP8 : do['up']
}
smap = ['##############################################',
'####################### #################',
'##################### # ###############',
'###################### ### ###########',
'################## ##### ####',
'################ ######## ###### ####',
'############### #################### ####',
'################ ###### ##',
'######## ####### ###### # # # ##',
'######## ###### ### ##',
'######## ##',
'#### ###### ### # # # ##',
'#### ### ########## #### ##',
'#### ### ########## ###########=##########',
'#### ################## ##### #####',
'#### ### #### ##### #####',
'#### # #### #####',
'######## # #### ##### #####',
'######## ##### ####################',
'##############################################',
]
###drawing###
def draw():
global fov_px, fov_py, fov_map, first
global fov_init, fov_recompute, smap
if first:
wh = window_height
ww = window_width
first = False
libtcod.console_clear(0)
libtcod.console_set_fore(0, ww, wh, libtcod.white)
libtcod.console_print_left(0, 1, 1, libtcod.BKGND_NONE,
"IJKL : move around")
libtcod.console_set_fore(0, ww, wh, libtcod.black)
libtcod.console_put_char(0, fov_px, fov_py, '#',
libtcod.BKGND_NONE)
for y in range(window_height):
for x in range(window_width):
if smap[y][x] == '=':
libtcod.console_put_char(0, x, y,
libtcod.CHAR_DHLINE,
libtcod.BKGND_NONE)
if not fov_init:
fov_init = True
fov_map = libtcod.map_new(window_width, window_height)
for y in range(window_height):
for x in range(window_width):
if smap[y][x] == ' ':
libtcod.map_set_properties(fov_map, x, y, True, True)
elif smap[y][x] == '=':
libtcod.map_set_properties(fov_map, x, y, True, False)
if fov_recompute:
fov_recompute = False
libtcod.map_compute_fov(fov_map, fov_px, fov_py, fov_radius, True)
for y in range(window_height):
for x in range(window_width):
affect, cell = 'dark', 'ground'
if libtcod.map_is_in_fov(fov_map, x, y):
affect = 'light'
if (smap[y][x] == '#'):
cell = 'wall'
color = fov_colors['%s %s' % (affect, cell)]
libtcod.console_set_back(0, x, y, color, libtcod.BKGND_SET)
###game state updates###
def update(key):
global fov_py, fov_px, fov_recompute, smap
key = get_key(key)
if key in keys:
dx, dy = keys[key]
if smap[fov_py+dy][fov_px+dx] == ' ':
libtcod.console_put_char(0, fov_px, fov_py, ' ',
libtcod.BKGND_NONE)
fov_px = fov_px + dx
fov_py = fov_py + dy
libtcod.console_put_char(0, fov_px, fov_py, '#',
libtcod.BKGND_NONE)
fov_recompute = True
###initialization and main loop###
font = os.path.join('fonts', 'arial12x12.png')
libtcod.console_set_custom_font(font, libtcod.FONT_LAYOUT_TCOD | libtcod.FONT_TYPE_GREYSCALE)
libtcod.console_init_root(window_width, window_height, 'Python Tutorial', False)
while not libtcod.console_is_window_closed():
draw()
libtcod.console_flush()
key = libtcod.console_wait_for_keypress(True)
update(key)
if key.vk == libtcod.KEY_ESCAPE:
break
I receive the following errors, again I have all the needed files in the folder and am on Windows.
Error for listing 2:
Traceback (most recent call last):
File "roguelike_practice1.py", line 167, in <module>
draw()
File "roguelike_practice1.py", line 100, in draw
libtcod.console_set_fore(0, ww, wh, libtcod.white)
File "c:\Users\cshenkan\CloudStation\Programming\Libtcod\Project 2\libtcodpy.p
y", line 764, in console_set_fore
_lib.TCOD_console_set_fore(con, x, y, col)
File "c:\Python27\lib\ctypes\__init__.py", line 378, in __getattr__
func = self.__getitem__(name)
File "c:\Python27\lib\ctypes\__init__.py", line 383, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'TCOD_console_set_fore' not found
I run into this TCOD_console_set_fore error a bunch. But say I comment that out, I get the same error but with another function such as TCOD_console_set_back, and others.
Not sure why I'm getting these errors. Using Python 2.7.9 32 bit, and libtcod 1.5.1 I believe. Running Windows 7 64 bit. Keep in mind I can get other programs to run that don't require any of those set_foreground and variation functions, or the print_left function or whatever other functions aren't working. But I'm sure it one or two issues affecting all the functions that wont work. \
If anyone has any ideas, I've spent a ton of time looking online to no avail for info. And the forum for libtcod takes days for administrator approval to join - lame.
Anyway thanks in advance! Ask me any questions or if you need clarification.
TCOD 1.5.1 renamed some functions, so that is why your two listings are crashing.
Version 1.5.1 renamed console_set_foreground_color to console_set_default_foreground,console_set_background_color to console_set_default_background, console_set_fore and console_set_back to console_set_char_foreground and console_set_char_background respectively, and console_wait_for_keypress has been replaced with sys_wait_for_event.
Also, console_print_left has been replaced by console_print_ex, which has an extra 'alignment' parameter between background and the string to print.
It appears that those functions were deprecated in 1.5.1. I can find them in 1.5.0, but neither in 1.5.1 nor 1.5.2. I think you would have to use console_print_ex or console_print_rect_ex instead.
Otherwise you could off course switch back to 1.5.0.
I've only just started coding, so I thought I would try and make something simple, however, I can't select the objects from my ls, I know the error is in my def attrLockT and was wondering if anyone could help me to fix this issue and understand what I am doing wrong?
import maya.cmds as cmds
#Selects the attributes
sat = ['.tx', '.ty', '.tz']
sar = ['.rx', '.ry', '.rz']
sas = ['.sx', '.sy', '.sz']
#Creates the list of currently selected objects
myList = cmds.ls(sl = True)
#Lock the translate attributes of the selected objects
def attrLockT(*args):
checkAttr=cmds.getAttr (myList[0] + sat)
if (checkAttr == 0):
cmds.setAttr(myList[0] + sat, lock = 1)
#Delete window if it is already open
if cmds.window('animationCtrl', exists=True):
cmds.deleteUI('animationCtrl', window=True)
#Setup the window
cmds.window(
'animationCtrl',
title = "Animation Controls",
widthHeight = (300, 500),
s = False)
form = cmds.formLayout()
tabs = cmds.tabLayout(innerMarginWidth=5, innerMarginHeight=5)
cmds.formLayout(
form,
edit=True,
attachForm=(
(tabs, 'top', 0),
(tabs, 'left', 0),
(tabs, 'bottom', 0),
(tabs, 'right', 0)))
#Layout for the first tab
child1 = cmds.gridLayout( numberOfRowsColumns=(4, 3) , cwh = (100, 50))
cmds.text(label = "")
cmds.text(label = "Lock", align = "center", h = 20, w = 250)
cmds.text(label = "")
cmds.button(label = "Translate", h = 300, w = 250, c = attrLockT)
cmds.button(label = "Rotate", h = 50, w = 250)
cmds.button(label = "Scale", h = 50, w = 250)
cmds.text(label = "")
cmds.text(label = "Unlock", align = "center", h = 20, w = 250)
cmds.text(label = "")
cmds.button(label = "Translate", h = 50, w = 250)
cmds.button(label = "Rotate", h = 50, w = 250)
cmds.button(label = "Scale", h = 50, w = 250)
cmds.setParent( '..' )
#Layout for the second tab
child2 = cmds.rowColumnLayout(numberOfColumns=3)
cmds.button()
cmds.button()
cmds.button()
cmds.setParent( '..' )
cmds.tabLayout(
tabs,
edit=True,
tabLabel=((child1, 'Lock/Unlock'), (child2, 'Keyable/Unkeyable')))
cmds.showWindow('animationCtrl')
The error that is thrown is
# Error: coercing to Unicode: need string or buffer, list found
# Traceback (most recent call last):
# File "<maya console>", line 16, in attrLockT
# TypeError: coercing to Unicode: need string or buffer, list found
Does this work?
myList[0] + sat
Is myList[0] type of list ? Because the sat variable is certainly list.
If myList is just a list of string then myList[0] will be just one element of type string and it will produce an error.
Simplify your program, just leave only locking routine and window with button to see what will happen, be sure that the right name of an object + attribute is passed to getAttr - just string like 'obj.attrib'.
Some python specific clues for your function
If you need to sum two lists:
[ objName + attName for objName, attName in zip(myList, sat) ]
that will result, for example, in ['obj1.tx', 'obj2.ty', 'obj3.tz']
If you need apply a list of attributes to an object:
[ myList[0] + a for a in sat ]
that will result in ['obj1.tx', 'obj1.ty', 'obj1.tz']
If you need apply the same list of attributes to all objects:
[ objName + attName for objName in myList for attName in sat ]
will result in ['obj1.tx', 'obj1.ty', 'obj1.tz', 'obj2.tx', ..., 'obj3.tz']
Then you can call your locking function over that result list:
def locker(a):
checkAttr = cmds.getAttr(a)
if (checkAttr == 0):
cmds.setAttr(a, lock = 1)
and finally it should look:
def attrLockT(*args):
atrlist = [ ..... ]
for a in atrlist:
locker(a)
Two issues:
first, you want to loop through the individual attributes and concatenate them with object names:
def lockTranslate(*args):
for obj in mylist:
for attr in ['.tx', '.ty', '.tz']:
cmds.setAttr(obj + "." + attr, l=True)
second, and maybe more important, you will likely have problems the scope of your functions. In the form you have it typed in, variables like myList and sat, etc are accessible to the function through closure - it will work if you execute all of this in the listener, but if you break the closure (for example, if this goes into a function that gets called by another function) things wont work -- myList will be stuck pointing at whatever was selected when the function was defined.
In this particular case you probably want to just operate on selection instead of inheriting myList:
def lockTranslate(*args):
for obj in cmds.ls(sl=True, type = 'transform'):
for attr in ['.tx', '.ty', '.tz']:
cmds.setAttr(obj + "." + attr, l=True)