Python capture Keystrokes values in text file on OS X - python

I am trying to monitor keystrokes on my Macbook on order to build a statistics analyzer. But how can I isolate the chars from "event" which is more something like :
NSEvent: type=KeyDown loc=(850,248) time=66551.8 flags=0x100 win=0x0
winNum=0 ctxt=0x0 chars="l" unmodchars="l" repeat=0 keyCode=37
So do anyone know how to, based on the script posted below, fulfill a .txt doc with the value of chars (from NSEvent) ? I need a text file with a the pressed keys in order to run my other script on it and analyze the frequency etc...
Thanks in advance ;)
#!/usr/bin/python
# -*- coding: utf-8 -*-
from AppKit import NSApplication, NSApp
from Foundation import NSObject, NSLog
from Cocoa import NSEvent, NSKeyDownMask
from PyObjCTools import AppHelper
class AppDelegate(NSObject):
def applicationDidFinishLaunching_(self, notification):
mask = NSKeyDownMask
NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(mask, handler)
def handler(event):
try:
print event
except KeyboardInterrupt:
AppHelper.stopEventLoop()
def main():
app = NSApplication.sharedApplication()
delegate = AppDelegate.alloc().init()
NSApp().setDelegate_(delegate)
AppHelper.runEventLoop()
if __name__ == '__main__':
main()

#!/usr/bin/python2.6
# You _must_ turn on assistive devices under Accessibility prefpane
# for any of this code to work. Otherwise it won't do anything.
from Cocoa import *
from Foundation import *
from PyObjCTools import AppHelper
import keycode
import string
import sys
class AppDelegate(NSObject):
def applicationDidFinishLaunching_(self, aNotification):
NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSKeyDownMask, handler)
def handler(event):
if event.type() == NSKeyDown and keycode.tostring(event.keyCode()) in string.printable:
print keycode.tostring(event.keyCode())
def main():
app = NSApplication.sharedApplication()
delegate = AppDelegate.alloc().init()
NSApp().setDelegate_(delegate)
AppHelper.runEventLoop()
if __name__ == '__main__':
main()
I dug around a bit and found github user 'gurgeh's OSX modifications for selfspy in his branch - https://github.com/gurgeh/selfspy/blob/new_activity/sniff_cocoa.py.
I put a few of my own ideas into it and this is the result. Kudos to gurgeh for figuring out how to capture window change events - this makes the key logger much more interesting since you could basically ignore apps that don't provide interesting events, or for the statistically minded, graph out which apps you use the most and what you're doing in them..
#!/usr/bin/python2.6
import exceptions
import sys
from Foundation import NSObject, NSLog
from AppKit import NSApplication, NSApp, NSWorkspace
from Cocoa import *
from Quartz import CGWindowListCopyWindowInfo, kCGWindowListOptionOnScreenOnly, kCGNullWindowID
from PyObjCTools import AppHelper
import keycode
evtypes = dict(
NSLeftMouseDown = 1,
NSLeftMouseUp = 2,
NSRightMouseDown = 3,
NSRightMouseUp = 4,
NSMouseMoved = 5,
NSLeftMouseDragged = 6,
NSRightMouseDragged = 7,
NSMouseEntered = 8,
NSMouseExited = 9,
NSKeyDown = 10,
NSKeyUp = 11,
NSFlagsChanged = 12,
NSAppKitDefined = 13,
NSSystemDefined = 14,
NSApplicationDefined = 15,
NSPeriodic = 16,
NSCursorUpdate = 17,
NSScrollWheel = 22,
NSTabletPoint = 23,
NSTabletProximity = 24,
NSOtherMouseDown = 25,
NSOtherMouseUp = 26,
NSOtherMouseDragged = 27
)
evtypes_rev = dict([[v,k] for k,v in evtypes.items()])
class Hooker(object):
def __call__(self, *args, **kwargs):
try:
evt = kwargs.get('event')
del kwargs['event']
items = ' '.join( [ x[0]+"="+unicode(x[1]) for x in kwargs.iteritems()] )
print "%20s | %22s | %s" % ( self.__class__.__name__, evtypes_rev[evt.type()], items)
except Exception as e:
print 'Horrific error!', e
AppHelper.stopEventLoop()
sys.exit(0)
class KeyHooker(Hooker): pass
class MouseButtonHooker(Hooker): pass
class MouseMoveHooker(Hooker): pass
class ScreenHooker(Hooker): pass
class SniffCocoa:
def __init__(self):
self.key_hook = KeyHooker()
self.mouse_button_hook = MouseButtonHooker()
self.mouse_move_hook = MouseMoveHooker()
self.screen_hook = ScreenHooker()
self.currentApp = None
def createAppDelegate (self) :
sc = self
class AppDelegate(NSObject):
def applicationDidFinishLaunching_(self, notification):
mask = (
NSKeyDownMask
| NSKeyUpMask
| NSLeftMouseDownMask
| NSLeftMouseUpMask
| NSRightMouseDownMask
| NSRightMouseUpMask
| NSMouseMovedMask
| NSScrollWheelMask
)
NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(mask, sc.handler)
return AppDelegate
def run(self):
NSApplication.sharedApplication()
delegate = self.createAppDelegate().alloc().init()
NSApp().setDelegate_(delegate)
self.workspace = NSWorkspace.sharedWorkspace()
AppHelper.runEventLoop()
def cancel(self):
AppHelper.stopEventLoop()
def handler(self, event):
try:
activeApps = self.workspace.runningApplications()
for app in activeApps:
if app.isActive():
if app.localizedName() != self.currentApp:
self.currentApp = app.localizedName()
options = kCGWindowListOptionOnScreenOnly
windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID)
for window in windowList:
if window['kCGWindowOwnerName'] == self.currentApp:
geom = window['kCGWindowBounds']
self.screen_hook( event=event,
name = window['kCGWindowName'],
owner = window['kCGWindowOwnerName'],
x = geom['X'],
y = geom['Y'],
w = geom['Width'],
h = geom['Height'])
break
break
loc = NSEvent.mouseLocation()
# mouse clicky buttons
if event.type() in ( NSLeftMouseDown, NSRightMouseDown, NSLeftMouseUp, NSRightMouseUp):
self.mouse_button_hook(event=event, x=loc.x, y=loc.y)
# mouse scrolly buttons
elif event.type() == NSScrollWheel:
if event.deltaY() > 0 and event.deltaY() < 0:
self.mouse_button_hook(event=event, x=loc.x, y=loc.y)
if event.deltaX() > 0 and event.deltaX() < 0:
self.mouse_button_hook(event=event, x=loc.x, y=loc.y)
# keys down
elif event.type() in ( NSKeyDown, NSKeyUp ):
flags = event.modifierFlags()
modifiers = [] # OS X api doesn't care it if is left or right
if (flags & NSControlKeyMask):
modifiers.append('CONTROL')
if (flags & NSAlternateKeyMask):
modifiers.append('ALTERNATE')
if (flags & NSCommandKeyMask):
modifiers.append('COMMAND')
self.key_hook(event=event, key=event.keyCode(), char=keycode.tostring( event.keyCode() ), mods=modifiers, is_repeat=event.isARepeat())
# Mouse moved
elif event.type() == NSMouseMoved:
self.mouse_move_hook(event=event, x=loc.x, y=loc.y)
else:
pass
except ( KeyboardInterrupt ) as e:
print 'handler', e
AppHelper.stopEventLoop()
if __name__ == '__main__':
sc = SniffCocoa()
sc.run()

For using Keycode module. Just clone it from here and run "sudo setup.py install" . You will have keycode module
https://github.com/abarnert/pykeycode

Related

NameError: name 'packet' is not defined - RLBot

I'm trying to write a script to record player movement in Rocket League using the RLBot framework. I've got very minimal experience with code and I've been getting the error:
Traceback (most recent call last):
File "c:/Users/Julian/AppData/Local/RLBotGUIX/RLBotPackDeletable/RLBotPack-master/RLBotPack/CustomMutators/playerRecorder.py", line 27, in <module>
class playerRecorder(BaseScript):
File "c:/Users/Julian/AppData/Local/RLBotGUIX/RLBotPackDeletable/RLBotPack-master/RLBotPack/CustomMutators/playerRecorder.py", line 45, in playerRecorder
for car in packet.game_cars:
NameError: name 'packet' is not defined
Packet is defined within def run(self): but I'm still getting an error for it not being defined. Below is my full script from within VS Code. Any help is appreciated.
from typing import Optional
from rlbot.agents.base_agent import BaseAgent, GameTickPacket, SimpleControllerState
import os
import time
import math
from rlbot.agents.base_agent import BaseAgent, SimpleControllerState
from rlbot.utils.structures.game_data_struct import GameTickPacket
from rlbot.utils.game_state_util import GameState, BallState, CarState, Physics, Vector3 as vector3, Rotator
import random
from rlbot.agents.base_script import BaseScript
from rlbot.utils.game_state_util import GameState
DIRECTORY_LOCATION = "C:\Logs\Recorder\log"
randNum = random.randint(0,9999999999)
# Extending the BaseScript class is purely optional. It's just convenient / abstracts you away from
# some strange classes like GameInterface
class playerRecorder(BaseScript):
def __init__(self):
super().__init__("playerRecorder")
packet = self.get_game_tick_packet()
self.writeFile = open(DIRECTORY_LOCATION+"\\"+"HumanLog"+str(car.team)+"-"+str(randNum), "w")
def run(self):
while True:
packet = self.get_game_tick_packet()
get_output(packet)
sleep(1 / 3)
print("test")
for car in packet.game_cars:
if not car.is_bot:
team = car.team
index = car.index
break
def get_output(self, game_tick_packet):
#***************************************************************
packet = self.get_game_tick_packet()
goodTeam = str(car.team)
goodLoc = packet.game_cars[car.index].physics.location
goodLocX = str(goodLoc.x)
goodLocY = str(goodLoc.y)
goodLocZ = str(goodLoc.z)
goodRot = packet.game_cars[car.index].physics.rotation
goodRotP = str(goodRot.pitch)
goodRotY = str(goodRot.yaw)
goodRotR = str(goodRot.roll)
goodVel = packet.game_cars[car.index].physics.velocity
goodVelX = str(goodVel.x)
goodVelY = str(goodVel.y)
goodVelZ = str(goodVel.z)
goodAngVel = packet.game_cars[car.index].physics.angular_velocity
goodAngVelX = str(goodAngVel.x)
goodAngVelY = str(goodAngVel.y)
goodAngVelZ = str(goodAngVel.z)
hasWC = str(packet.game_cars[car.index].has_wheel_contact)
isSS = str(packet.game_cars[car.index].is_super_sonic)
jumped = str(packet.game_cars[car.index].jumped)
dJumped = str(packet.game_cars[car.index].double_jumped)
bst = str(packet.game_cars[car.index].boost)
ballLoc = packet.game_ball.physics.location
ballLocX = str(ballLoc.x)
ballLocY = str(ballLoc.y)
ballLocZ = str(ballLoc.z)
ballVel = packet.game_ball.physics.velocity
ballVelX = str(ballVel.x)
ballVelY = str(ballVel.y)
ballVelZ = str(ballVel.z)
self.writeFile.write(goodTeam+";"+
goodLocX+","+goodLocY+","+goodLocZ+";"+
goodRotP+","+goodRotY+","+goodRotR+";"+
goodVelX+","+goodVelY+","+goodVelZ+";"+
goodAngVelX+","+goodAngVelY+","+goodAngVelZ+";"+
hasWC+";"+isSS+";"+jumped+";"+dJumped+";"+bst+";"+
ballLocX+","+ballLocY+","+ballLocZ+";"+
ballVelX+","+ballVelY+","+ballVelZ)
self.writeFile.write("\n")
## WRITE OPPONENT
badIndex = -1
for i in range(len(packet.game_cars)):
if i != car.index:
badIndex = i
break
assert badIndex != car.index
assert badIndex != -1
badTeam = str(packet.game_cars[badIndex].team)
badLoc = packet.game_cars[badIndex].physics.location
badLocX = str(badLoc.x)
badLocY = str(badLoc.y)
badLocZ = str(badLoc.z)
badRot = packet.game_cars[badIndex].physics.rotation
badRotP = str(badRot.pitch)
badRotY = str(badRot.yaw)
badRotR = str(badRot.roll)
badVel = packet.game_cars[badIndex].physics.velocity
badVelX = str(badVel.x)
badVelY = str(badVel.y)
badVelZ = str(badVel.z)
badAngVel = packet.game_cars[badIndex].physics.angular_velocity
badAngVelX = str(badAngVel.x)
badAngVelY = str(badAngVel.y)
badAngVelZ = str(badAngVel.z)
badhasWC = str(packet.game_cars[badIndex].has_wheel_contact)
badisSS = str(packet.game_cars[badIndex].is_super_sonic)
badjumped = str(packet.game_cars[badIndex].jumped)
baddJumped = str(packet.game_cars[badIndex].double_jumped)
badbst = str(packet.game_cars[badIndex].boost)
self.writeFile.write(badTeam+";"+
badLocX+","+badLocY+","+badLocZ+";"+
badRotP+","+badRotY+","+badRotR+";"+
badVelX+","+badVelY+","+badVelZ+";"+
badAngVelX+","+badAngVelY+","+badAngVelZ+";"+
badhasWC+";"+badisSS+";"+badjumped+";"+baddJumped+";"+badbst)
self.writeFile.write("\n")
## WRITE ACTION
self.writeFile.write(str(action.throttle)+";"+str(action.steer)+";"+str(action.pitch)+";"+str(action.yaw)+";"+str(action.action.roll)+";"+str(action.jump)+";"+str(action.boost))
self.writeFile.write("\n")
##*****************************************************
return action
In the run(...) function you should type self.get_output(packet) instead of get_output(). You have to pass a packet as a parameter to a function and also you should write self before the name of a function because it's inside a class. I think you also misspelled the parameter of the get_output function because you've named it game_tick_packet and in the function you are using variable named just a packet.

Embedding visvis figure in a wx application

The code bellow try to embed visvis figure in a wx application to make a movie with 3D data. The problem is that everytime I rum the code, I get the error
"./src/unix/glx11.cpp(86): assert "xid" failed in SetCurrent(): window
must be shown" right after calling Figure = app.GetFigureClass()
self.fig = Figure(self)
I spent some time researching this error, but none of the answers suited me. Does anyone knows how to fix it?
import wx
import h5py
import numpy as np
import visvis as vv
app = vv.use('wx')
class CPlot3D (wx.Frame) :
"""
Class for plotting 3D Dirac
"""
def data_for_plotting (self, frame_number) :
"""
Load the data to be plotted for the frame with the frame_number
"""
frame = str(self.frame_names[frame_number])
return self.f[frame][...]
def draw_curent_frame (self, event=None) :
"""
Display the current frame
"""
# Load data
data = self.data_for_plotting (self.frame_number.GetValue())
try :
self.volume_plot.SetData (data)
except AttributeError :
vv.clf()
self.volume_plot = vv.volshow (data, clim=(self.global_min, self.global_max), renderStyle='mip', cm=vv.CM_JET)
a = vv.gca()
vv.ColormapEditor(a)
def GetTicks (axis_num, min_val, max_val, label_format="%.2f") :
size = data.shape[axis_num]
# Number of ticks
nticks = int(np.ceil(np.log2(size)))
nticks += 1 - nticks % 2 # Make <nticks> odd
ticks_position = np.linspace(0, size-1, nticks)
ticks_label = map( lambda x : label_format % x, np.linspace(min_val, max_val, nticks) )
return dict( zip(ticks_position, ticks_label) )
a.axis.xTicks = GetTicks(0, self.x_min, self.x_max)
a.axis.xLabel = "x (rel. units)"
a.axis.yTicks = GetTicks(1, self.y_min, self.y_max)
a.axis.yLabel = "y (rel. units)"
a.axis.zTicks = GetTicks(2, self.z_min, self.z_max)
a.axis.zLabel = "z (rel. units)"
self.fig.Draw()
def __init__ (self, parent, file_name, title="Plot Dirac 3D") :
# Open files
self.f = h5py.File (file_name, 'r')
# Extract the dimension
self.x_gridDIM = int(self.f['x_gridDIM'][...])
self.y_gridDIM = int(self.f['y_gridDIM'][...])
self.z_gridDIM = int(self.f['z_gridDIM'][...])
self.dx = self.f['dx'][...]
self.x_min = self.f['x_min'][...]
self.x_max = self.x_min + self.x_gridDIM * self.dx
self.y_min = self.f['y_min'][...]
self.y_max = self.y_min + self.y_gridDIM * self.dx
self.z_min = self.f['z_min'][...]
self.z_max = self.z_min + self.z_gridDIM * self.dx
# Collect the frame names
self.frame_names = []
for key in self.f.keys () :
try : self.frame_names.append (int(key))
except ValueError: pass
self.frame_names.sort ()
print "\nGet global maximum and minimum..."
# Find the min and max values in all the frames
for frame_number in range(len(self.frame_names)) :
data = self.data_for_plotting (frame_number)
try :
self.global_min = min( self.global_min, data.min() )
self.global_max = max( self.global_max, data.max() )
except AttributeError :
self.global_min = data.min()
self.global_max = data.max()
print "\nStart animation..."
# Create GUI
dw, dh = wx.DisplaySize()
wx.Frame.__init__ (self, parent, title=title, size=(0.4*dw, 0.6*dh) )
self.ConstructGUI ()
self.Center()
self.Show ()
wx.EVT_CLOSE(self, self.on_close)
self.On_animation_button ()
def on_close (self, event) :
try : self.animation_timer.Stop()
except AttributeError : pass
self.Destroy()
def ConstructGUI (self) :
"""
Make a GUI
"""
######################### Navigation bar ##############################
panel = wx.Panel(self)
boxsizer = wx.BoxSizer (wx.HORIZONTAL)
# Frame number indicator
boxsizer.Add (wx.StaticText(panel, label="Frame Number:"))
self.frame_number = wx.SpinCtrl (panel, value="0", min=0, max=len(self.frame_names)-1)
self.frame_number.Bind (wx.EVT_SPINCTRL, self.draw_curent_frame )
boxsizer.Add (self.frame_number)
# Go to the beginning button
self.go_beginnign_button = wx.Button (panel, label="<<")
self.Bind (wx.EVT_BUTTON, self.go_to_beginning, self.go_beginnign_button)
boxsizer.Add (self.go_beginnign_button)
# Animation button
self.animation_button_start_label = "Play animation "
self.animation_button_stop_label = "STOP animation"
self.animation_button = wx.Button (panel, label=self.animation_button_start_label)
self.Bind (wx.EVT_BUTTON, self.On_animation_button, self.animation_button)
boxsizer.Add (self.animation_button)
# Go to the end button
self.go_end_button = wx.Button (panel, label=">>")
self.Bind (wx.EVT_BUTTON, self.go_to_end, self.go_end_button)
boxsizer.Add (self.go_end_button)
panel.SetSizer (boxsizer)
############################# Setting up visvis binding #######################################
Figure = app.GetFigureClass()
self.fig = Figure(self)
################################### Layout #####################################################
sizer = wx.BoxSizer (wx.VERTICAL)
sizer.Add (panel, flag=wx.CENTER)
sizer.Add(self.fig._widget, 1, flag=wx.EXPAND)
self.SetSizer(sizer)
self.SetAutoLayout(True)
self.Layout()
def On_animation_button (self, event=None) :
"""
<self.animation_button> was clicked
"""
if self.animation_button.GetLabel() == self.animation_button_start_label :
# Begin playing animation
# Set up timer for animation
timer_id = wx.NewId ()
self.animation_timer = wx.Timer (self, timer_id)
self.animation_timer.Start (200)
def on_animation_timer (event) :
self.draw_curent_frame()
position = self.frame_number.GetValue()
if position > len(self.frame_names)-2 : self.On_animation_button ()
else : self.frame_number.SetValue (position+1)
wx.EVT_TIMER (self, timer_id, on_animation_timer)
# Channing the button's label
self.animation_button.SetLabel(self.animation_button_stop_label)
else : # Stop playing animation
self.animation_timer.Stop ()
del self.animation_timer
# Channing the button's label
self.animation_button.SetLabel(self.animation_button_start_label)
def go_to_beginning (self, event) :
"""
<self.go_beginnign_button> was clicked
"""
self.frame_number.SetValue (0)
self.draw_curent_frame()
def go_to_end (self, event) :
"""
<self.go_end_button> was clicked
"""
self.frame_number.SetValue (len(self.frame_names)-1)
self.draw_curent_frame()
if __name__ == '__main__' :
import sys
app.Create()
# Loading files
if len(sys.argv) <> 2 :
openFileDialog = wx.FileDialog(None, "Open HDF5 file to load 3D Dirac", "", "",
"HDF5 files (*.hdf5)|*.hdf5", wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_CHANGE_DIR)
# Check whether user canceled
if openFileDialog.ShowModal() == wx.ID_CANCEL:
print "Error: file name is needed as argument"
exit()
else : filename = openFileDialog.GetPath()
else : filename = sys.argv[1]
CPlot3D (None, filename)
app.Run ()
When you call On_animation_button() manually, your frame is not actually shown yet, even though you had called Show() on it because, at least with X11, showing happens asynchronously. So you need to delay calling it until later. This can be done by e.g. binding a lambda doing this to EVT_SIZE event (because by the time you get it, the window is already initialized) or just by using CallAfter().

Drone's motion is unstable with ROS topics

Drone's motion is not stable with rostopics...what can I do ?
import rospy
import time
#import library untuk mengirim command dan menerima data navigasi dari quadcopter
from geometry_msgs.msg import Twist
from std_msgs.msg import String
from std_msgs.msg import Empty
from ardrone_autonomy.msg import Navdata
#import class status untuk menentukan status ddari quadcopter
from drone_status import DroneStatus
COMMAND_PERIOD = 1000
class AutonomousFlight():
def __init__(self):
self.status = ""
rospy.init_node('forward', anonymous=False)
self.rate = rospy.Rate(10)
self.pubTakeoff = rospy.Publisher("ardrone/takeoff",Empty, queue_size=10)
self.pubLand = rospy.Publisher("ardrone/land",Empty, queue_size=10)
self.pubCommand = rospy.Publisher('cmd_vel',Twist, queue_size=10)
self.command = Twist()
#self.commandTimer = rospy.Timer(rospy.Duration(COMMAND_PERIOD/1000.0),self.SendCommand)
self.state_change_time = rospy.Time.now()
rospy.on_shutdown(self.SendLand)
def SendTakeOff(self):
self.pubTakeoff.publish(Empty())
self.rate.sleep()
def SendLand(self):
self.pubLand.publish(Empty())
def SetCommand(self, linear_x, linear_y, linear_z, angular_x, angular_y, angular_z):
self.command.linear.x = linear_x
self.command.linear.y = linear_y
self.command.linear.z = linear_z
self.command.angular.x = angular_x
self.command.angular.y = angular_y
self.command.angular.z = angular_z
self.pubCommand.publish(self.command)
self.rate.sleep()
if __name__ == '__main__':
try:
i = 0
uav = AutonomousFlight()
while not rospy.is_shutdown():
uav.SendTakeOff()
if i <= 30 :
uav.SetCommand(0,0,1,0,0,0)
i+=1
elif i<=60 :
uav.SetCommand(0,0,0,0,0,0)
i+=1
else:
uav.SendLand()
except rospy.ROSInterruptException:
pass
I need to just takeoff, go up and go to hover mode,
uav.SendTakeOff()
if i <= 30 :
uav.SetCommand(0,0,1,0,0,0)
i+=1
elif i<=60 :
uav.SetCommand(0,0,0,0,0,0)
after take off, this code makes the drone go to little back and some random motion and going up and going to hover mode. How can I fix this ?

API Exporting Issue

I need someone's expertise on this exporting problem of mine.
How it works: Select a camera (animated or not is optional) >> File >> Export Selection >> File Type : .chan (need to load this script as a plugin)
Here's where the problem starts. It is able to create a .text file, however, it is not 'exporting' or writing out the contents into the text file and the file size is of zero bytes.
I am making use of the current API that it has been coded, modifying the code to add in some maya cmds
Can someone kindly help me out?
import math, sys, string, os
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMayaAnim as OpenMayaAnim
import maya.cmds as cmds
import maya.mel as mel
kPluginTranslatorTypeName = "chan Export/Import"
kVersionNumber = "0.5a"
camSel = []
win_name = "chan_window"
class CustomNodeTranslator(OpenMayaMPx.MPxFileTranslator):
def __init__(self):
OpenMayaMPx.MPxFileTranslator.__init__(self)
def haveWriteMethod(self):
return True
def haveReadMethod(self):
return True
def filter(self):
return " .chan"
def defaultExtension(self):
return "chan"
def writer( self, fileObject, optionString, accessMode ):
try:
fullName = fileObject.fullName()
fileHandle = open(fullName,"w")
selectList = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList(selectList)
node = OpenMaya.MObject()
depFn = OpenMaya.MFnDependencyNode()
path = OpenMaya.MDagPath()
iterator = OpenMaya.MItSelectionList(selectList)
animationTime = OpenMayaAnim.MAnimControl()
maxTime = int(animationTime.maxTime().value())
minTime = int(animationTime.minTime().value())
while (iterator.isDone() == 0):
iterator.getDependNode(node)
depFn.setObject(node)
iterator.getDagPath(path, node)
cameraObject = OpenMaya.MFnCamera(path)
transform = OpenMaya.MFnTransform(path)
chanMe = fileExporter(transform, minTime, maxTime, cameraObject)
for all in chanMe():
fileHandle.write(all)
iterator.next()
fileHandle.close()
except:
sys.stderr.write( "Failed to write file information\n")
raise
def processLine( self, lineStr ):
self.importTheChan.writeFrameData(lineStr)
class fileExporter():
""" module for exporting chan files from application. arguments: object, startFrame, endFrame """
def __init__(self, transform, startAnimation, endAnimation, cameraObj):
self.fileExport = []
self.transform = transform
self.cameraObj = cameraObj
self.start = startAnimation
self.end = endAnimation
self.exportWin()
def exportWin(self):
self.expWindow = cmds.window(w=150, h=100, title = "Export Selection" )
cmds.columnLayout( adjustableColumn=True )
form = cmds.formLayout(numberOfDivisions=100)
cmds.radioCollection()
self.chk1 = cmds.radioButton( label='option1', onc = self.opt1On, ofc = self.opt1Off )
self.chk2 = cmds.radioButton( label='option2', onc = self.opt2On, ofc = self.opt2Off )
self.okayBtn = cmds.button(label='okay!', command=self.runSel, width=150, height=35)
cmds.formLayout(form, edit=True, attachForm=[\
(self.chk1, 'top', 15),\
(self.chk1, 'left', 15),\
(self.chk2, 'top', 30),\
(self.chk2, 'left', 15),\
(self.okayBtn, 'top', 50),\
(self.okayBtn, 'left', 15)])
cmds.showWindow( self.expWindow )
def opt1On(self, args):
print "User checked option1"
startAnimation = cmds.playbackOptions(query=True, minTime=True)
endAnimation = cmds.playbackOptions(query=True, maxTime=True)
self.start = startAnimation
self.end = endAnimation
def opt1Off(self, args):
print "User un-checked option1"
cmds.radioButton(self.chk2, edit = True, enable = True)
self.start = ""
self.end = ""
def opt2On(self, args):
print "User checked option2"
startAnimation = cmds.findKeyframe(which='first')
endAnimation = cmds.findKeyframe(which='last')
self.start = startAnimation
self.end = endAnimation
#self.start.append(int(startAnimation))
#self.end.append(int(endAnimation))
def opt2Off(self, args):
print "User un-checked option2"
self.start = ""
self.end = ""
def runSel(self, args):
chkVal1 = cmds.radioButton(self.chk1, query=True, sl=1)
chkVal2 = cmds.radioButton(self.chk2, query=True, sl=1)
if chkVal1 == 1:
print "opt1 Pressed!"
print self.start
print self.end
self.test()
self.closeWindow()
elif chkVal2 == 1:
print "opt2 Pressed!"
print self.start
print self.end
self.test()
self.closeWindow()
else:
cmds.warning("Check an option")
def closeWindow(self):
cmds.deleteUI(self.expWindow, window=True)
def test(self):
self.actualExp(self.transform, self.start, self.end, self.cameraObj)
def actualExp(self, transform, startAnimation, endAnimation, cameraObj):
mayaGlobal = OpenMaya.MGlobal()
mayaGlobal.viewFrame(OpenMaya.MTime(1))
# Converts the float arguement into integer
for i in range(int(startAnimation), int(endAnimation + 1)):
focalLength = cameraObj.focalLength()
vFilmApp = cameraObj.verticalFilmAperture()
focalOut = 2 math.degrees(math.atan(vFilmApp 25.4/ (2 focalLength)))
myEuler = OpenMaya.MEulerRotation()
spc = OpenMaya.MSpace.kWorld
trans = transform.getTranslation(spc)
rotation = transform.getRotation(myEuler)
rotVector = OpenMaya.MVector(myEuler.asVector())
self.fileExport.append((str(i) + '\t' + str(trans[0]) + "\t" + str(trans[1]) + "\t" + str(trans[2]) + "\t" + str(math.degrees(rotVector[0])) + "\t" + str(math.degrees(rotVector[1])) + "\t" + str(math.degrees(rotVector[2])) + "\t" + str(focalOut) + "\n"))
mayaGlobal.viewFrame(OpenMaya.MTime(i+1))
def __call__(self, args):
return self.fileExport
def radianToDegree(self, radians):
outDegrees = 0.0
outDegrees = (float(radians) / (math.pi)) 180
return outDegrees
# creator
def translatorCreator():
return OpenMayaMPx.asMPxPtr( CustomNodeTranslator() )
# initialize the script plug-in
def initializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.registerFileTranslator(kPluginTranslatorTypeName, None, translatorCreator)
except:
sys.stderr.write( "Failed to register translator: %s" % kPluginTranslatorTypeName )
raise
# uninitialize the script plug-in
def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.deregisterFileTranslator( kPluginTranslatorTypeName )
except:
sys.stderr.write( "Failed to deregister translator: %s" % kPluginTranslatorTypeName )
raise
the __call__ method is what's supposed to provide the contents of the file. It returns self.fileExport, which is an empty list that is not getting populated.
The problem here is the writer method of the plugin will not wait for your exportWin UI to return the user inputs when you call
chanMe = fileExporter(transform, minTime, maxTime, cameraObject)
By the time the user has entered the inputs, the statements that follow have already been executed:
for all in chanMe():
fileHandle.write(all)
iterator.next()
fileHandle.close()
That is why plugin-based file exporters like these have their options UI tucked away in the option box. These options will be passed prior to call to the plugin's writer().
You will need to export your options UI code (in a certain specific format) using MEL in another script file and specify the name of that file in the optionsScriptName param of the registerFileTranslator call. There is a communication protocol that needs to be followed for communication between this options UI and the writer plugin itself. RobTheBloke's awesome post illustrates this process.
Ideally, the writer() method should have all the details it needs for computing and exporting without having to wait for user input.
Alternatively, if you prefer to have your own UI window and more control over the flow of things, you could write the exporter not as a plugin, but as a simple MEL/Python module. You could still use the power of the API.
Hope this helped!

Python Cocos2d: tiles show up only once

I'm working on a custom tiled map loader. Seems to work fine, I don't get any errors, but the screen only shows up 1 tile of each type.
this is the file structure:
/main.py
/other/render2.py
/other/render.py
here's the render2.py file:
import pyglet, json
from pyglet.window import key
from pyglet.gl import *
from ConfigParser import SafeConfigParser
from cocos.layer import *
from cocos.batch import *
from cocos.sprite import Sprite
class renderer( Layer ):
#init function
def __init__(self):
super( renderer, self ).__init__()
#call function, returns the map as a list of sprites, and coordinates
def __call__(self, mapname):
#runs the map file parser
parser = SafeConfigParser()
#reads the map file
try:
world = parser.read('maps/'+mapname+'.txt')
print world
except IOError:
return
#These variables the config from the map file
tileSize = int(parser.get('config', 'tilesize'))
layers = int(parser.get('config', 'layers'))
mapList = []
#the super mega advanced operation to render the mapList
for i in range(0,layers):
layer = json.loads(parser.get('layer'+str(i), 'map'))
tileType = parser.get('layer'+str(i), 'tiletype')
nTiles = int(parser.get('layer'+str(i), 'tiles'))
tileSet = []
#this over here loads all 16 tiles of one type into tileSet
for n in range(0, nTiles):
tileSet.append(Sprite("image/tiles/"+tileType+"/"+str(n)+".png", scale = 1, anchor = (0,0)))
for x in range(0, len(layer)):
for y in range(0, len(layer[x])):
X = (x*tileSize)
Y = (y*tileSize)
total = [tileSet[layer[x][y]], i, X, Y]
print layer[x][y], tileSet[layer[x][y]]
mapList.append(total)
return mapList
This is an example of what this returns :
[<cocos.sprite.Sprite object at 0x060910B0>, 0, 0,0 ]
[<cocos.sprite.Sprite object at 0x060910B0> , 0, 64,64 ]
It returns a huge list with a lot of sublists like these in it.
when I call it from the main.py file, it only draws the last tile of each kind.
here's the main.py file:
import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
import pyglet
import threading,time
from pyglet import clock
from pyglet.gl import *
from cocos.director import *
from cocos.menu import *
from cocos.scene import *
from cocos.layer import *
from cocos.actions import *
from cocos.batch import *
from cocos.sprite import Sprite
from other.render2 import renderer
import random; rr = random.randrange
class Background(ScrollableLayer):
def __init__(self):
super(Background, self).__init__()
world = renderer()
bg = world('sampleidea')
batch = BatchNode()
for i in range(0, len(bg)):
l= bg[i][1]
x= bg[i][2]
y= bg[i][3]
spr = bg[i][0]
spr.position =(x,y)
batch.add(spr, z = l)
self.add(batch)
class Menu(Layer):
def __init__(self):
super(Menu, self).__init__()
title = Sprite('image/title.png' )
title.position = (400,520)
self.add( title )
def start():
director.set_depth_test()
background = Background()
menu = Menu()
scene = Scene(background, menu)
return scene
def init():
director.init( do_not_scale=True, resizable=True, width=1280, height=720)
def run(scene):
director.run( scene )
if __name__ == "__main__":
init()
s = start()
run(s)
What am I doing wrong? I have an older render.py, which does work, but I remade it since it loaded each sprite file for each tile. That took way to long to load on big maps.
This is the old render.py I've been using before.
It's quite different since it used different map files too.
import pyglet, json
from pyglet.window import key
from pyglet.gl import *
from ConfigParser import SafeConfigParser
from cocos.layer import *
from cocos.batch import *
from cocos.sprite import Sprite
class renderer( Layer ):
def __init__(self):
super( renderer, self ).__init__()
def __call__(self, mapname):
parser = SafeConfigParser()
try:
world = parser.read('maps/'+mapname+'.txt')
print world
except IOError:
print("No world file!")
return
tilesize = json.loads(parser.get('data', 'tilesize'))
world = json.loads(parser.get('data', 'world'))
maplist = []
for l in range(len(world)):
for x in range(len(world[l])):
for y in range(len(world[l][x])):
if world[l][x][y] != None:
foldername = str(world[l][x][y][0])
imagename = str(world[l][x][y][1])
spr = Sprite("image/tiles/"+foldername+"/"+imagename+".png", scale = 1, anchor = (0,0))
X = (x*tilesize)
Y = (y*tilesize)
total = [spr, l, X, Y]
maplist.append(total)
return maplist
Is it possible to make the new "render" to work?
The problem is that my new optimized "renderer" creates a bunch of
cocos.sprite.Sprite objects, instead of just loading Image files as i thought it would. The code in my question only repositioned the same sprite object over and over again this way. To solve this, the way to do it is by opening the image with pyglet.image.load(), and creating sprite objects with that.
example:
f = pyglet.image.load('sprite.png')
batch = CocosNode()
batch.position = 50, 100
add(batch)
for i in range(0, 200):
test = Sprite(f)
test.position = i*10,i*10
batch.add( test )

Categories