Skip to content

Instantly share code, notes, and snippets.

@d33tah
Created September 12, 2010 20:30
Show Gist options
  • Select an option

  • Save d33tah/576416 to your computer and use it in GitHub Desktop.

Select an option

Save d33tah/576416 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from pynk import *
from config import * #might as well be removed - defines only "login" and "password"
set_debug(True)
from time import sleep
import math
from PIL import Image
import os
import sys
import urllib
from panda3d.core import loadPrcFileData
from direct.showbase.DirectObject import DirectObject
from panda3d.core import Point2, Point3, TextNode, BitMask32
from panda3d.core import CollisionRay, CollisionNode, CollisionTraverser, CollisionHandlerQueue, GeomNode
from direct.interval.FunctionInterval import Wait
from direct.gui.DirectGui import *
def mul_tuple(t,y):
return tuple([x*y for x in t])
def scale_to_tex(tex):
xsize = tex.getXSize()
ysize = tex.getYSize()
if xsize > ysize:
yscale = float(ysize)/xsize
xscale = 1
else:
xscale = float(xsize)/ysize
yscale = 1
return (xscale,1,yscale)
def blinkTask(task):
if task.time < 0.1:
return task.cont
base.setBackgroundColor(*C_BLACK)
return task.done
def blink(str):
if str: debug(">>>> "+str+'\n')
base.setBackgroundColor(*C_RED)
taskMgr.add(blinkTask,'blink')
def photo_to_tex(nk,url):
filename = nk.cache_filename(url)
if not os.path.exists(filename+'.png'):
nk.get_url(url,cached=True)
Image.open(filename).save(filename+'.png')
else:
debug("PPH: Found cache for %s\n" % url)
return loader.loadTexture(filename+'.png')
def loadObject(tex = None, pos = Point2(0,0), depth = 55, scale = 1, transparency = True,tag = []):
obj = loader.loadModel("square")
obj.reparentTo(camera)
obj.setPos(Point3(pos.getX(), depth, pos.getY()))
obj.setDepthTest(False)
obj.node().setIntoCollideMask(BitMask32.bit(1))
obj.setScale(scale)
obj.setTransparency(1)
if tex:
obj.setTexture(tex, 1)
for param in tag:
obj.node().setTag(param, str(tag[param]))
return obj
C_WHITE=(255,255,255)
C_BLACK=(0,0,0)
C_RED=(255,0,0)
C_GREEN=(0,255,0)
C_BLUE=(0,0,255)
C_PURPLE=(255,0,255)
C_YELLOW=(255,255,0)
C_CYAN=(0,255,255)
class CenterTriangle:
def __init__(self,nk,size=13):
self.size = size
self.nk = nk
self.obj = loadObject(tex=loader.loadTexture('triangle.png'),
pos=Point2(0,0),
tag={'id':'center_triangle'},
scale=size)
def draw_url(self,url):
tex = photo_to_tex(self.nk,url)
self.obj.setTexture(tex)
scale = mul_tuple(scale_to_tex(tex),self.size)
self.obj.setScale(scale)
class ObjectsRing:
def __init__(self,world,r,nk):
self.world = world
self.r = r
self.nk = nk
self.objects = {}
self.task = None
def clear(self):
if self.task is not None:
taskMgr.remove(self.task)
self.task = None
for i in range(len(self.objects)):
self.objects[i].remove()
#"""
def drawObjectsTask(self,param,task):
n = len(param)
self.scale = min(2,abs(self.r/(float(n)/4.001 - 1 )))
print self.scale
for i in range(n):
deg=i*(6.2832/n)
x=math.sin(deg)*self.r
y=math.cos(deg)*self.r
object_ = self.drawObject(x,y,i,param[i])
if object_:
object_.setScale(self.scale)
self.objects[i]=object_
yield task.cont
#"""
"""
def drawObjectsTask(self,param,task):
import math
count=len(param)
sideCount=math.ceil(count/4.0)-5
def side(itemCount):
scale=1.0*sideCount/itemCount
pos=[]
for i in range(itemCount):
x=1.0*i/itemCount-2**.5/2
#x**2+y**2=1
y=(1-x**2)**.5
pos.append((x*sideCount,y*sideCount))
return pos,scale
pos,s=side(sideCount)
#do 4 sides
for i in range(len(pos)):
x=pos[i][0] ; y=pos[i][1]
self.drawObject(x,y,i,param[i])
yield task.cont
for i in range(len(pos)):
x=pos[i][0] ; y=pos[i][1]
self.drawObject(y,x,i,param[int(i+sideCount)])
yield task.cont
for i in range(len(pos)):
x=pos[i][0] ; y=pos[i][1]
self.drawObject(-y,x,i,param[int(i+sideCount*2)])
yield task.cont
for i in range(len(pos)):
x=pos[i][0] ; y=pos[i][1]
self.drawObject(x,-y,i,param[int(i+sideCount*3)])
yield task.cont
"""
def drawObjects(self,param):
self.task = taskMgr.add(self.drawObjectsTask, 'drawObjectsTask', extraArgs=[param], appendTask=True)
class ProfilesRing(ObjectsRing):
def __init__(self, *args,**kwargs):
self.profiles = {}
ObjectsRing.__init__(self,*args,**kwargs)
def drawObject(self,x,y,i,profile):
self.profiles[i]=profile
try:
url = profile.get_details().avatar.thumb_url
except UserBannedError:
blink("User banned error")
return
except UserDeletedError:
blink("User deleted error")
return
else:
if not url:
blink("Thumbnail not found error")
return
tex=photo_to_tex(self.nk,url)
return loadObject(pos=Point2(x,y),
tag={'id':'friendPhoto', 'number':i},
tex=tex,
scale=scale_to_tex(tex),
)
class PhotosRing(ObjectsRing):
def __init__(self, *args,**kwargs):
self.photos = {}
ObjectsRing.__init__(self,*args,**kwargs)
def drawObject(self,x,y,i,photo):
self.photos[i] = photo
url = photo.thumb_url
tex=photo_to_tex(self.nk,url)
return loadObject(pos=Point2(x,y),
tag={'id':'galleryPhoto', 'number':i},
tex=tex,
scale=scale_to_tex(tex),
)
class World(DirectObject):
def __init__(self):
#self.qt_app = QtGui.QApplication(sys.argv)
base.setBackgroundColor(*C_BLACK)
self.focusText = OnscreenText("Click some Image!",
fg=(1,1,1,1),
pos = (-1.3, .95),
align = TextNode.ALeft,
mayChange = 1)
self.nameText = OnscreenText("",
fg=(1,1,1,1),
pos = (-1.3, .90),
align = TextNode.ALeft,
mayChange = 1)
#login, ok = QtGui.QInputDialog.getText(None, 'Input Dialog', 'Podaj swoj login:')
#password, ok = QtGui.QInputDialog.getText(None, 'Input Dialog', 'Podaj swoje haslo:')
self.nk = PyNK()
self.nk.login(login,password)
self.nk.cache_cfg["PROFILE"] = True
print self.nk.basic_auth
self.center_triangle = CenterTriangle(nk=self.nk)
self.profiles_ring = ProfilesRing(r=14,world=self,nk=self.nk)
self.photos_ring = PhotosRing(r=12,world=self,nk=self.nk)
if len(sys.argv)==2:
self.current_profile = NK_profile(nk=self.nk,url=sys.argv[1])
self.current_profile.get_details()
else:
self.current_profile = self.nk.my_profile
self.nameText.setText("Now viewing: %s" % self.current_profile.name )
friends = self.current_profile.get_friends()
#"""
print "selecting friends..."
little_friends = ( lambda friend: int(friend.get_details().photos_count) > 100 )
friends = list(sorted(friends, key=lambda friend: friend.friends_count))
#friends = list(reversed(sorted(friends, key=lambda friend: friend.friends_count)))
#friends = [friend for friend in friends if little_friends(friend) ]
print "done (%s)" % len(friends)
#"""
self.profiles_ring.drawObjects(friends)
self.nk.logout()
self.nk.login(login,password)
self.control_setup()
self.collision_setup()
self.current_focus = None
self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
def mouseTask(self,task):
if not base.mouseWatcherNode.hasMouse(): return task.cont
obj = self.collision_test(force_id='friendPhoto')
if obj != self.current_focus:
if self.current_focus:
self.current_focus.setScale(1)
if obj:
obj.setScale(render,3)
self.current_focus = obj
number = int(obj.findNetTag('id').getTag('number'))
profile = self.profiles_ring.profiles[number]
profile.get_details()
self.focusText.setText(profile.name)
else:
self.focusText.setText('Click some Image!')
return task.cont
def collision_setup(self):
self.pickerNode = CollisionNode('mouseRay')
self.pickerNP = camera.attachNewNode(self.pickerNode)
self.pickerRay = CollisionRay()
self.pickerNode.addSolid(self.pickerRay)
self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
self.collisionTraverser = CollisionTraverser()
self.handlerQueue = CollisionHandlerQueue()
self.collisionTraverser.addCollider(self.pickerNP, self.handlerQueue)
def control_setup(self):
self.accept('escape', sys.exit)
self.accept('q', sys.exit)
self.accept("mouse1", self.onLMB)
self.accept("mouse3", self.onRMB)
self.accept("alt-up", self.alt_up)
self.accept("alt", self.alt_down)
def alt_down(self):
self.altText = OnscreenText("ALT key pressed",
pos = (-1.3, -.95),
align = TextNode.ALeft,
mayChange = 1,
fg=C_RED+(1,),
)
def alt_up(self):
if self.altText is not None:
self.altText.remove()
self.altText = None
def collision_test(self,force_id=''):
mpos = base.mouseWatcherNode.getMouse()
self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
self.collisionTraverser.traverse(render)
if self.handlerQueue.getNumEntries() > 0:
self.handlerQueue.sortEntries()
pickedObj = self.handlerQueue.getEntry(0).getIntoNodePath()
if pickedObj:
if force_id:
obj_id = pickedObj.findNetTag('id').getTag('id')
if force_id != obj_id:
return None
return pickedObj
def onLMB(self):
if not base.mouseWatcherNode.hasMouse(): return
pickedObj = self.collision_test()
if pickedObj:
obj_id = pickedObj.findNetTag('id').getTag('id')
if obj_id=='friendPhoto':
number = int(pickedObj.findNetTag('id').getTag('number'))
profile = self.profiles_ring.profiles[number]
try:
url = profile.get_details().avatar.get_image_url()
except UserBannedError:
blink("User banned error")
return
except UserDeletedError:
blink("User deleted error")
return
if url is not None:
self.center_triangle.draw_url(url)
self.nameText.setText("%s (%s)" % (profile.name, profile.friends_count))
else:
blink("URL is empty")
self.photos_ring.clear()
self.nk.logout()
self.nk.login(login,password)
photos = profile.get_photos(first_only=False)
self.photos_ring.drawObjects(photos)
elif obj_id=='galleryPhoto':
#try:
number = int(pickedObj.findNetTag('id').getTag('number'))
url = self.photos_ring.photos[number].get_image_url()
self.center_triangle.draw_url(url)
#except AttributeError:
#base.setBackgroundColor(*C_RED)
#taskMgr.add(self.blink,'blink')
else:
pass
def onRMB(self):
if not base.mouseWatcherNode.hasMouse(): return
pickedObj = self.collision_test()
if pickedObj:
obj_id = pickedObj.findNetTag('id').getTag('id')
if obj_id=='friendPhoto':
self.profiles_ring.clear()
self.photos_ring.clear()
number = int(pickedObj.findNetTag('id').getTag('number'))
profile = self.profiles_ring.profiles[number]
try:
friends = profile.get_friends()
except UserBannedError:
blink("User banned error")
return
except UserDeletedError:
blink("User deleted error")
return
self.nk.logout()
self.nk.login(login,password)
self.profiles_ring.drawObjects(friends)
if __name__=='__main__':
loadPrcFileData('', 'window-title Panda3d - PyNK photo demo')
loadPrcFileData('', 'win-origin 50 0')
import direct.directbase.DirectStart
w = World()
run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment