-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPosterImage.py
155 lines (122 loc) · 4.61 KB
/
PosterImage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
from pandac.PandaModules import *
from direct.showbase.DirectObject import DirectObject
from direct.stdpy import threading
class PosterImage(DirectObject):
LoadedPosters = {}
def __init__(self, url):
DirectObject.__init__(self)
self.url = URLSpec(url)
self.image = None
# Create a condition variable so we can block on load.
self.cvar = threading.Condition()
self.done = False
# Create an initial 1x1 white texture.
self.tex = Texture(Filename(self.url.getPath()).getBasename())
p = PNMImage(1, 1)
p.fill(0.5, 0.5, 1)
self.tex.load(p)
if self.url.getScheme() == 'maze':
# Here's a special case: instead of querying an HTTP
# server, we get the local poster data from the maze
# object.
self.loadPlayerPoster()
elif self.url.getScheme() == '':
# Another special case: this is a local file. This should
# only happen from the local player.
self.loadLocalPoster()
else:
# Otherwise, we get the poster data from the internet.
self.loadingTask = taskMgr.add(self.load, 'loadPoster', taskChain = 'loadPoster')
def loadLocalPoster(self):
try:
file = open(self.url.cStr(), 'rb')
except IOError:
print "Couldn't open file %s" % (self.url)
self.__markDone()
return
data = file.read()
self.loadImageData(data)
def loadPlayerPoster(self):
try:
doId = int(self.url.getServer())
i = int(self.url.getPath()[1:])
except ValueError:
print "Invalid maze URL: %s" % (self.url)
self.__markDone()
return
base.w.relatedObjectMgr.requestObjects([doId], allCallback = self.__gotMaze, timeout = 5)
def __gotMaze(self, mazeList):
maze = mazeList[0]
if not maze:
print "No such maze: %s" % (doId)
self.__markDone()
return
i = int(self.url.getPath()[1:])
try:
data = maze.posterData[i]
except IndexError:
print "Maze %s has no poster %s" % (doId, i)
self.__markDone()
return
self.loadImageData(data)
def block(self):
""" Block the current thread until the texture is loaded. """
self.cvar.acquire()
while not self.done:
self.cvar.wait()
self.cvar.release()
def __markDone(self):
""" Called in the sub-thread to make sure that the texture is
loaded. """
self.cvar.acquire()
self.done = True
self.cvar.notifyAll()
self.cvar.release()
def load(self, task):
""" Downloads the poster image and creates a Texture object. """
try:
http = HTTPClient.getGlobalPtr()
except NameError:
print "No HTTPClient available."
self.__markDone()
return
doc = http.getDocument(self.url)
rf = Ramfile()
doc.downloadToRam(rf)
if not doc.isValid():
print "Failed to load %s: %s %s" % (self.url, doc.getStatusCode(), doc.getStatusString())
self.__markDone()
return
# We've downloaded the URL, so now the image data is available
# in RAM. Load it into a PNMImage.
self.loadImageData(rf.getData())
def loadImageData(self, data):
""" Once the image data has been retrieved, load it into a
texture. """
data = StringStream(data)
p = PNMImage()
# First, read the header to get the image size
if not p.readHeader(data):
print "Failed to read image header from %s" % (self.url)
self.__markDone()
return
# Ensure the image is a power of 2
self.tex.considerRescale(p)
# Also ensure that it isn't larger than 256x256
xsize = min(p.getReadXSize(), 256)
ysize = min(p.getReadYSize(), 256)
p.setReadSize(xsize, ysize)
# Now, read the actual image data, scaling it to the requested
# size as we read it.
data.seekg(0)
if not p.read(data):
print "Failed to read image data from %s" % (self.url)
self.__markDone()
return
self.image = p
# Finally, load the PNMImage into the Texture.
self.tex.load(p)
self.tex.setMinfilter(Texture.FTLinearMipmapLinear)
self.tex.setMagfilter(Texture.FTLinear)
print "Loaded %s" % (self.url)
self.__markDone()