Integrated major improvements from shooter2 project, including slick UI module!

This commit is contained in:
cecilkorik 2017-05-08 23:17:52 -07:00
parent a9ac67e6d6
commit 65019a5e43
25 changed files with 991 additions and 140 deletions

View file

@ -1,5 +1,5 @@
from roc_core import * from roc_core import *
import universe import roc_engine
import pipeline import pipeline
import inputs import inputs
import physics import physics

BIN
data/ui/button_bg_corner.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
data/ui/button_bg_edge.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
data/ui/button_corner.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
data/ui/button_edge.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
data/ui/frame_bg_corner.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
data/ui/frame_bg_edge.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
data/ui/frame_corner.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
data/ui/frame_edge.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -2,5 +2,5 @@
<datatag name="planet_scale" data="float"/> <datatag name="planet_scale" data="float"/>
<datatag name="system_scale" data="float"/> <datatag name="system_scale" data="float"/>
<datatag name="ship_scale" data="float"/> <datatag name="ship_scale" data="float"/>
<datatag name=" <datatag name="xx" data="float"/>
</xml_binary_packing> </xml_binary_packing>

View file

@ -19,6 +19,12 @@
<attribute name="y" data="float" default="1.0"/> <attribute name="y" data="float" default="1.0"/>
<attribute name="z" data="float" default="1.0"/> <attribute name="z" data="float" default="1.0"/>
</datatag> </datatag>
<datatag name="scale_to_tex" data="bool" default=""/>
<datatag name="rot" optional="yes">
<attribute name="x" data="float" default="0.0"/>
<attribute name="y" data="float" default="0.0"/>
<attribute name="z" data="float" default="0.0"/>
</datatag>
</datatag> </datatag>
<datatag name="material"> <datatag name="material">
<datatag name="ref" data="string"/> <datatag name="ref" data="string"/>

View file

@ -1,10 +1,14 @@
<models> <models>
<mesh id="mesh_sprite"> <mesh id="mesh_sprite">
<sprite/> <centered_sprite/>
</mesh> </mesh>
<mesh id="mesh_centered_sprite"> <mesh id="mesh_centered_sprite">
<centered_sprite/> <centered_sprite/>
</mesh> </mesh>
<mesh id="mesh_offset_sprite">
<sprite/>
</mesh>
<model id="m_test"> <model id="m_test">
<render layer="0"> <render layer="0">
<mesh><ref>mesh_sprite</ref><scale x="200" y="200"/></mesh> <mesh><ref>mesh_sprite</ref><scale x="200" y="200"/></mesh>
@ -31,10 +35,187 @@
</model> </model>
<model id="m_dralthi"> <model id="m_dralthi">
<render layer="0"> <render layer="0">
<mesh><ref>mesh_centered_sprite</ref><scale x="50" y="50"/></mesh> <mesh><ref>mesh_centered_sprite</ref><scale x="40" y="40"/></mesh>
<material><ref>mat_dralthi</ref></material> <material><ref>mat_dralthi</ref></material>
</render> </render>
</model> </model>
<model id="ui_frame_tl">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/></mesh>
<material><ref>mat_ui_frame_corner</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/></mesh>
<material><ref>mat_ui_frame_bg_corner</ref></material>
</render>
</model>
<model id="ui_frame_tc">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/></mesh>
<material><ref>mat_ui_frame_edge</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/></mesh>
<material><ref>mat_ui_frame_bg_edge</ref></material>
</render>
</model>
<model id="ui_frame_tr">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="90.0"/></mesh>
<material><ref>mat_ui_frame_corner</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="90.0"/></mesh>
<material><ref>mat_ui_frame_bg_corner</ref></material>
</render>
</model>
<model id="ui_frame_cl">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="270.0"/></mesh>
<material><ref>mat_ui_frame_edge</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="270.0"/></mesh>
<material><ref>mat_ui_frame_bg_edge</ref></material>
</render>
</model>
<model id="ui_frame_cc">
<render layer="0">
<mesh><ref>mesh_sprite</ref></mesh>
<material><ref>mat_blank</ref></material>
</render>
</model>
<model id="ui_frame_cr">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="90.0"/></mesh>
<material><ref>mat_ui_frame_edge</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="90.0"/></mesh>
<material><ref>mat_ui_frame_bg_edge</ref></material>
</render>
</model>
<model id="ui_frame_bl">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="270.0"/></mesh>
<material><ref>mat_ui_frame_corner</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="270.0"/></mesh>
<material><ref>mat_ui_frame_bg_corner</ref></material>
</render>
</model>
<model id="ui_frame_bc">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="180.0"/></mesh>
<material><ref>mat_ui_frame_edge</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="180.0"/></mesh>
<material><ref>mat_ui_frame_bg_edge</ref></material>
</render>
</model>
<model id="ui_frame_br">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="180.0"/></mesh>
<material><ref>mat_ui_frame_corner</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="180.0"/></mesh>
<material><ref>mat_ui_frame_bg_corner</ref></material>
</render>
</model>
<model id="ui_button_tl">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/></mesh>
<material><ref>mat_ui_button_corner</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/></mesh>
<material><ref>mat_ui_button_bg_corner</ref></material>
</render>
</model>
<model id="ui_button_tc">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/></mesh>
<material><ref>mat_ui_button_edge</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/></mesh>
<material><ref>mat_ui_button_bg_edge</ref></material>
</render>
</model>
<model id="ui_button_tr">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="90.0"/></mesh>
<material><ref>mat_ui_button_corner</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="90.0"/></mesh>
<material><ref>mat_ui_button_bg_corner</ref></material>
</render>
</model>
<model id="ui_button_cl">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="270.0"/></mesh>
<material><ref>mat_ui_button_edge</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="270.0"/></mesh>
<material><ref>mat_ui_button_bg_edge</ref></material>
</render>
</model>
<model id="ui_button_cc">
<render layer="0">
<mesh><ref>mesh_sprite</ref></mesh>
<material><ref>mat_blank</ref></material>
</render>
</model>
<model id="ui_button_cr">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="90.0"/></mesh>
<material><ref>mat_ui_button_edge</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="90.0"/></mesh>
<material><ref>mat_ui_button_bg_edge</ref></material>
</render>
</model>
<model id="ui_button_bl">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="270.0"/></mesh>
<material><ref>mat_ui_button_corner</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="270.0"/></mesh>
<material><ref>mat_ui_button_bg_corner</ref></material>
</render>
</model>
<model id="ui_button_bc">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="180.0"/></mesh>
<material><ref>mat_ui_button_edge</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="180.0"/></mesh>
<material><ref>mat_ui_button_bg_edge</ref></material>
</render>
</model>
<model id="ui_button_br">
<render layer="0">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="180.0"/></mesh>
<material><ref>mat_ui_button_corner</ref></material>
</render>
<render layer="1">
<mesh><ref>mesh_sprite</ref><scale_to_tex/><rot z="180.0"/></mesh>
<material><ref>mat_ui_button_bg_corner</ref></material>
</render>
</model>
</models> </models>

View file

@ -13,7 +13,7 @@
<uniform/> <uniform/>
</texture> </texture>
<material id="mat_blank"> <material id="mat_blank">
<texture ref="t_white" type="diffuse"/> <texture ref="t_white" type="noaa"/>
<texture ref="tnm_flat" type="normal"/> <texture ref="tnm_flat" type="normal"/>
</material> </material>
<texture id="t_test"> <texture id="t_test">
@ -29,6 +29,56 @@
<file>tex/dralthi.png</file> <file>tex/dralthi.png</file>
</texture> </texture>
<texture id="t_ui_button_corner">
<file>ui/button_corner.png</file>
</texture>
<texture id="t_ui_button_edge">
<file>ui/button_edge.png</file>
</texture>
<texture id="t_ui_button_bg_corner">
<file>ui/button_bg_corner.png</file>
</texture>
<texture id="t_ui_button_bg_edge">
<file>ui/button_bg_edge.png</file>
</texture>
<texture id="t_ui_frame_corner">
<file>ui/frame_corner.png</file>
</texture>
<texture id="t_ui_frame_edge">
<file>ui/frame_edge.png</file>
</texture>
<texture id="t_ui_frame_bg_corner">
<file>ui/frame_bg_corner.png</file>
</texture>
<texture id="t_ui_frame_bg_edge">
<file>ui/frame_bg_edge.png</file>
</texture>
<material id="mat_ui_button_corner">
<texture ref="t_ui_button_corner" type="noaa"/>
</material>
<material id="mat_ui_button_edge">
<texture ref="t_ui_button_edge" type="noaa"/>
</material>
<material id="mat_ui_button_bg_corner">
<texture ref="t_ui_button_bg_corner" type="noaa"/>
</material>
<material id="mat_ui_button_bg_edge">
<texture ref="t_ui_button_bg_edge" type="noaa"/>
</material>
<material id="mat_ui_frame_corner">
<texture ref="t_ui_frame_corner" type="noaa"/>
</material>
<material id="mat_ui_frame_edge">
<texture ref="t_ui_frame_edge" type="noaa"/>
</material>
<material id="mat_ui_frame_bg_corner">
<texture ref="t_ui_frame_bg_corner" type="noaa"/>
</material>
<material id="mat_ui_frame_bg_edge">
<texture ref="t_ui_frame_bg_edge" type="noaa"/>
</material>
<texture id="t_test_plasma"> <texture id="t_test_plasma">
<file>tex/plasma1.png</file> <file>tex/plasma1.png</file>
</texture> </texture>

View file

@ -1,5 +1,9 @@
class enum(object): class enum(object):
def __init__(self, names=[]):
for i, name in enumerate(names):
setattr(self, name, i)
def __len__(self): def __len__(self):
return len([x for x in dir(self) if x[0] != '_']) return len([x for x in dir(self) if x[0] != '_'])
@ -83,3 +87,21 @@ tt.diffuse = 0 # the diffuse texture sets the colors and general brightness of
tt.emissive = 1 # this texture is blended with the diffuse texture as the light level drops (this can be used to add running lights or glow to a ship, or light up the dark side of a planet, otherwise pure "black" is a good choice) tt.emissive = 1 # this texture is blended with the diffuse texture as the light level drops (this can be used to add running lights or glow to a ship, or light up the dark side of a planet, otherwise pure "black" is a good choice)
tt.specular = 2 # adding a specular map allows you to add areas of low or high reflectivity to your texture tt.specular = 2 # adding a specular map allows you to add areas of low or high reflectivity to your texture
tt.normal = 3 # normal maps allow bump mapping and other tweaks, with each channel representing the direction of the normal (red = -1x to 1x, green = -1y to 1y, blue = 0z to 1z) tt.normal = 3 # normal maps allow bump mapping and other tweaks, with each channel representing the direction of the normal (red = -1x to 1x, green = -1y to 1y, blue = 0z to 1z)
tt.noaa = 4 # this replaces the diffuse texture, and is used for sprites that dont want to be antialiased
# UI stuff
ui_frametype = enum()
ui_frametype.grid = 0
ui_frametype.composite = 1
ui_frametype.model = 2
ui_postype = enum()
ui_postype.center = 0
ui_postype.relative = 1
ui_postype.absolute = 2
ui_filltype = enum()
ui_filltype.none = 0
ui_filltype.tile = 1
ui_filltype.stretch = 2

View file

@ -100,7 +100,14 @@ class TexFont(object):
else: else:
return self.charsizes[idx] return self.charsizes[idx]
def get_size(self, text):
total = 0
for i, letter in enumerate(text):
charidx = self.mapchar(letter)
x, y = self.charsize(charidx)
total += x
return (total, y)
def mapchar(self, char): def mapchar(self, char):
""" """

View file

@ -1,5 +1,18 @@
import enums import enums
class datastorage(object):
def __init__(self, readonly=False):
self.__ro = readonly
def __setattr__(self, name, value):
if name in ('__ro',):
object.__setattr__(self, name, value)
if self.__ro:
raise ValueError("Unable to set read-only property")
else:
object.__setattr__(self, name, value)
class gameobj(object): class gameobj(object):
def __init__(self, self.pos): def __init__(self, self.pos):
self.pos = pos self.pos = pos

View file

@ -1,77 +1,72 @@
import pygame import pygame
import collections import collections
def start_loop(): class GameTimer(object):
global g_timer, g_elapsed def __init__(self):
g_elapsed = 0 self.update_fps_count = None
g_elapsed_sec = 0.0
g_timer = pygame.time.get_ticks()
reset_fps_count()
def next_frame(skipping=False): def start_loop(self):
global g_timer, g_elapsed, g_elapsed_sec self.elapsed = 0
self.elapsed_sec = 0.0
self.timer = pygame.time.get_ticks()
self.reset_fps_count()
def next_frame(self, skipping=False):
newticks = pygame.time.get_ticks() newticks = pygame.time.get_ticks()
#if skipping: #if skipping:
# # reset g_timer to it's value from the previous frame # # reset self.timer to it's value from the previous frame
# g_timer -= g_elapsed # self.timer -= self.elapsed
g_elapsed = newticks - g_timer self.elapsed = newticks - self.timer
g_timer = newticks self.timer = newticks
g_elapsed_sec = float(g_elapsed) / 1000.0 self.elapsed_sec = float(self.elapsed) / 1000.0
if g_elapsed != 0: if self.elapsed != 0:
update_fps_count(g_elapsed) self.update_fps_count(self.elapsed)
def reset_fps_count(): def reset_fps_count(self):
global g_framelist, update_fps_count self.framelist = collections.deque()
g_framelist = collections.deque() self.update_fps_count = self.update_fps_count_empty
update_fps_count = update_fps_count_empty
def update_fps_count_empty(elapsed): def update_fps_count_empty(self, elapsed):
global g_framelist, update_fps_count self.framelist.append(elapsed)
g_framelist.append(elapsed) if len(self.framelist) >= 25:
if len(g_framelist) >= 25: self.update_fps_count = self.update_fps_count_full
update_fps_count = update_fps_count_full
def update_fps_count_full(elapsed): def update_fps_count_full(self, elapsed):
global g_framelist self.framelist.popleft()
g_framelist.popleft() self.framelist.append(elapsed)
g_framelist.append(elapsed)
def update_fps_count(elapsed):
"this is replaced with either the _empty or _full variant, depending on the situation"
pass
def elapsed(): def elapsed(self):
""" """
get the amount of time in milliseconds passed since the last frame was displayed get the amount of time in milliseconds passed since the last frame was displayed
""" """
return g_elapsed return self.elapsed
def elapsed_sec(): def elapsed_sec(self):
""" """
get the amount of time in seconds passed since the last frame was displayed get the amount of time in seconds passed since the last frame was displayed
""" """
return g_elapsed_sec return self.elapsed_sec
def num_frames(delay, offset=0): def num_frames(self, delay, offset=0):
""" """
if you want something to occur every "delay" milliseconds, if you want something to occur every "delay" milliseconds,
this will return the number of times you should make it happen this will return the number of times you should make it happen
in this particular frame (can be 0) in this particular frame (can be 0)
""" """
global g_elapsed, g_timer return int((self.timer - offset) / delay) - int((self.timer - self.elapsed - offset) / delay)
return int((g_timer - offset) / delay) - int((g_timer - g_elapsed - offset) / delay)
def loop_frames(delay, offset=0): def loop_frames(self, delay, offset=0):
return range(num_frames(delay, offset)) return range(num_frames(delay, offset))
def get_timer(): def get_timer(self):
return g_timer return self.timer
def average(d): def average(self, d):
#spf = (float(sum(g_framelist)) / (len(g_framelist) * 1000.0)) #spf = (float(sum(self.framelist)) / (len(self.framelist) * 1000.0))
if len(d) == 0: if len(d) == 0:
return 0.0 return 0.0
@ -88,15 +83,14 @@ def average(d):
return v2 return v2
def get_fps(): def get_fps(self):
global g_framelist #return ",".join([str(x) for x in sorted(self.framelist)])
#return ",".join([str(x) for x in sorted(g_framelist)]) if len(self.framelist) == 0.0:
if len(g_framelist) == 0.0:
return 0.0 return 0.0
spf = average(g_framelist) / 1000.0 spf = self.average(self.framelist) / 1000.0
if spf == 0.0: if spf == 0.0:
return 0.0 return 0.0
#print "%s < %s" % (1.0 / spf, g_framelist) #print "%s < %s" % (1.0 / spf, self.framelist)
return 1.0 / spf return 1.0 / spf

View file

@ -46,7 +46,9 @@ class Model_Manager(object):
def load_textypes(self): def load_textypes(self):
self.textypes = {} self.textypes = {}
self.textypes[enums.tt.diffuse] = TextureType(GL_TEXTURE0, GL_TEXTURE_2D, GL_CLAMP, GL_CLAMP, GL_LINEAR, GL_LINEAR) self.textypes[enums.tt.diffuse] = TextureType(GL_TEXTURE0, GL_TEXTURE_2D, GL_CLAMP, GL_CLAMP, GL_LINEAR, GL_LINEAR)
self.textypes[enums.tt.noaa] = TextureType(GL_TEXTURE0, GL_TEXTURE_2D, GL_REPEAT, GL_REPEAT, GL_NEAREST, GL_NEAREST)
self.textypes[enums.tt.emissive] = TextureType(GL_TEXTURE1, GL_TEXTURE_2D) self.textypes[enums.tt.emissive] = TextureType(GL_TEXTURE1, GL_TEXTURE_2D)
self.textypes[enums.tt.specular] = TextureType(GL_TEXTURE2, GL_TEXTURE_2D) self.textypes[enums.tt.specular] = TextureType(GL_TEXTURE2, GL_TEXTURE_2D)
self.textypes[enums.tt.normal] = TextureType(GL_TEXTURE3, GL_TEXTURE_2D) self.textypes[enums.tt.normal] = TextureType(GL_TEXTURE3, GL_TEXTURE_2D)
@ -97,6 +99,7 @@ class Model_Manager(object):
self.models = {} self.models = {}
for meshdata in mdldata.mesh: for meshdata in mdldata.mesh:
if meshdata['sprite']: if meshdata['sprite']:
if self.sprite_mesh == None:
self.sprite_mesh = SpriteMesh() self.sprite_mesh = SpriteMesh()
mesh = self.sprite_mesh mesh = self.sprite_mesh
elif meshdata['centered_sprite']: elif meshdata['centered_sprite']:
@ -266,14 +269,22 @@ class Material(object):
if texobj.uniform: if texobj.uniform:
if self.texcoords_uniform == self.texcoords_notimpl: if self.texcoords_uniform == self.texcoords_notimpl:
self.texcoords_uniform = texobj.texcoords self.texcoords_uniform = texobj.texcoords
self.texcoords = texobj.texcoords
else: else:
if prevtex: if prevtex:
assert texobj.texcoords(0.0, 0.0) == prevtex.texcoords(0.0, 0.0) and texobj.texcoords(1.0, 1.0) == prevtex.texcoords(1.0, 1.0) assert texobj.texcoords(0.0, 0.0) == prevtex.texcoords(0.0, 0.0) and texobj.texcoords(1.0, 1.0) == prevtex.texcoords(1.0, 1.0)
if self.texcoords == self.texcoords_notimpl: if self.texcoords == self.texcoords_notimpl:
self.texcoords = texobj.texcoords self.texcoords = texobj.texcoords
prevtex = texobj prevtex = texobj
def get_base_texture(self):
if enums.tt.noaa in self.textures:
t = self.textures[enums.tt.noaa]
else:
t = self.textures[enums.tt.diffuse]
return t
class Mesh(object): class Mesh(object):
@ -334,6 +345,12 @@ class SpriteMeshCentered(SpriteMesh):
Vertex(vect( 0.5, 0.5, 0.0), vect(0.0, 0.0, 1.0), (1.0, 1.0), None), Vertex(vect( 0.5, 0.5, 0.0), vect(0.0, 0.0, 1.0), (1.0, 1.0), None),
] ]
@staticmethod
def factory(meshdata):
s = SpriteMeshCentered()
s.scale
return s
class RenderLayer(object): class RenderLayer(object):
def __init__(self, layernum): def __init__(self, layernum):
self.id = layernum self.id = layernum
@ -343,6 +360,8 @@ class RenderLayer(object):
self.scale = [1.0, 1.0, 1.0] self.scale = [1.0, 1.0, 1.0]
self.displaylist = None self.displaylist = None
self.anim = "idle" self.anim = "idle"
self.rotations = None
self.tile = False
def load(self, layerdata): def load(self, layerdata):
meshdata = layerdata.mesh meshdata = layerdata.mesh
@ -352,6 +371,17 @@ class RenderLayer(object):
self.color = [matdata.color['r'], matdata.color['g'], matdata.color['b'], matdata.color['a']] self.color = [matdata.color['r'], matdata.color['g'], matdata.color['b'], matdata.color['a']]
self.scale = [meshdata.scale['x'], meshdata.scale['y'], meshdata.scale['z']] self.scale = [meshdata.scale['x'], meshdata.scale['y'], meshdata.scale['z']]
self.scale = [x * meshdata['scale'] for x in self.scale] self.scale = [x * meshdata['scale'] for x in self.scale]
self.rotations = [meshdata.rot['x'], meshdata.rot['y'], meshdata.rot['z']]
if meshdata['scale_to_tex']:
t = self.material.get_base_texture()
self.scale = [float(t.w), float(t.h), 1.0]
def get_base_texture(self):
if enums.tt.noaa in self.material.textures:
t = self.material.textures[enums.tt.noaa]
else:
t = self.material.textures[enums.tt.diffuse]
return t
def render(self): def render(self):
self.material.bind() self.material.bind()
@ -359,17 +389,29 @@ class RenderLayer(object):
glScalef(*self.scale) glScalef(*self.scale)
if self.color != None: if self.color != None:
glColor4f(*self.color) glColor4f(*self.color)
glRotatef(self.rotations[0], 1.0, 0.0, 0.0)
glRotatef(self.rotations[1], 0.0, 1.0, 0.0)
glRotatef(self.rotations[2], 0.0, 0.0, 1.0)
if self.displaylist == None: if self.displaylist == None:
self.displaylist = glGenLists(1) self.displaylist = glGenLists(1)
glNewList(self.displaylist, GL_COMPILE) glNewList(self.displaylist, GL_COMPILE)
self.mesh.draw(self.material.texcoords) if self.tile:
tcfunc = self.tile_texcoords
else:
tcfunc = self.material.texcoords
self.mesh.draw(tcfunc)
glEndList() glEndList()
#print "Drawing mesh %s" % ( self.displaylist, ) #print "Drawing mesh %s" % ( self.displaylist, )
glCallList(self.displaylist) glCallList(self.displaylist)
glPopMatrix() glPopMatrix()
def tile_texcoords(self, u, v):
t = self.material.get_base_texture()
u = u * self.scale[0] / t.w
v = v * self.scale[1] / t.h
return self.material.texcoords(u, v)
class ParticleLayer(RenderLayer): class ParticleLayer(RenderLayer):
def __init__(self, layernum): def __init__(self, layernum):
RenderLayer.__init__(self, layernum) RenderLayer.__init__(self, layernum)
@ -383,6 +425,15 @@ class Model(object):
def __init__(self): def __init__(self):
self.layers = [] self.layers = []
def get_size(self):
if not self.layers:
return (0.0, 0.0, 0.0)
for layer in self.layers:
return [layer.scale[i] for i in range(0, len(layer.scale))]
def load(self, data): def load(self, data):
tmplayers = [] tmplayers = []
for rend in data.render: for rend in data.render:
@ -404,6 +455,7 @@ class Model(object):
class TextModel(Model): class TextModel(Model):
def __init__(self, fontname, text, color=None, scale=None): def __init__(self, fontname, text, color=None, scale=None):
Model.__init__(self)
self.displaylist = None self.displaylist = None
self.fontname = fontname self.fontname = fontname
self.text = text self.text = text
@ -418,6 +470,10 @@ class TextModel(Model):
def instance(self): def instance(self):
return self return self
def get_size(self):
font = mgr.get_font(self.fontname)
return font.get_size(self.text)
def render(self): def render(self):
glPushMatrix() glPushMatrix()
glScalef(*self.scale) glScalef(*self.scale)

View file

@ -4,9 +4,9 @@ import video
import shader import shader
import models import models
import roc_main import roc_main
import universe import roc_engine
import config import config
base_universe = universe.base_universe base_engine = roc_engine.base_engine
def init2d(): def init2d():
init(videoinit=video.init2d) init(videoinit=video.init2d)
@ -29,8 +29,8 @@ def init(videoinit):
models.init() models.init()
def set_universe(new_universe): def set_engine(new_engine):
roc_main.set_universe(new_universe) roc_main.set_engine(new_engine)
def main(): def main():
roc_main.mainloop() roc_main.mainloop()

View file

@ -4,7 +4,7 @@ import pygame
from OpenGL.GL import * from OpenGL.GL import *
from py3dutil import vect, quat from py3dutil import vect, quat
class base_universe(object): class base_engine(object):
def __init__(self): def __init__(self):
pass pass
@ -20,7 +20,7 @@ class base_universe(object):
def render(self): def render(self):
pass pass
class tiled_universe(base_universe): class tiled_engine(base_engine):
def __init__(self): def __init__(self):
pass pass

View file

@ -10,20 +10,18 @@ import config
from OpenGL.GL import * from OpenGL.GL import *
def set_universe(new_universe): def set_engine(new_engine):
global g_universe global g_engine
g_universe = new_universe g_engine = new_engine
g_universe = None g_engine = None
def mainloop(): def mainloop():
global g_universe global g_engine
gametimer.start_loop()
while True: while True:
events = pygame.event.get() events = pygame.event.get()
gametimer.next_frame()
pygame.event.pump() pygame.event.pump()
for ev in events: for ev in events:
if ev.type == QUIT: if ev.type == QUIT:
@ -42,7 +40,7 @@ def mainloop():
video.predraw() video.predraw()
g_universe.frame(events) g_engine.frame(events)
video.next_frame() video.next_frame()

View file

@ -1,7 +1,6 @@
#import roc #import roc
import os import os
import sys import sys
sys.path.append(os.path.abspath('..'))
import roc import roc
import pygame import pygame
from OpenGL.GL import * from OpenGL.GL import *
@ -60,7 +59,7 @@ class partycle(object):
self.yd *= 0.985 self.yd *= 0.985
self.rot += self.rotd self.rot += self.rotd
class test_universe(roc.universe.base_universe): class test_engine(roc.engine.base_engine):
def __init__(self): def __init__(self):
self.font = models.mgr.fontlib["micross20"] self.font = models.mgr.fontlib["micross20"]
self.text1 = models.TextModel("micross20", "#$% 0123 ,,,, Hello world!\xa8\xa8\xa8F", (1.0, 1.0, 0.5, 1.0)) self.text1 = models.TextModel("micross20", "#$% 0123 ,,,, Hello world!\xa8\xa8\xa8F", (1.0, 1.0, 0.5, 1.0))
@ -168,7 +167,7 @@ class test_universe(roc.universe.base_universe):
roc.video.width = 1024 roc.video.width = 1024
roc.video.height = 768 roc.video.height = 768
roc.init2d() roc.init2d()
roc.set_universe(test_universe()) roc.set_engine(test_engine())
roc.main() roc.main()

View file

@ -122,17 +122,17 @@ class shader_manager(object):
try: try:
shaderinit() shaderinit()
except: except:
print("Shader type %s failed to initialize" % (shadername,)) print(("Shader type %s failed to initialize" % (shadername,)))
continue continue
try: try:
self.select("ffp") self.select("ffp")
except: except:
print("Shader type %s failed to access the fixed function pipeline" % (shadername,)) print(("Shader type %s failed to access the fixed function pipeline" % (shadername,)))
continue continue
try: try:
self.select("standard") self.select("standard")
except: except:
print("Shader type %s failed to load the \"standard\" vertex and fragment shaders" % (shadername,)) print(("Shader type %s failed to load the \"standard\" vertex and fragment shaders" % (shadername,)))
continue continue
workable_shaders.append(shadername) workable_shaders.append(shadername)
@ -171,28 +171,28 @@ class shader_manager(object):
except GLError: except GLError:
p = self.shaderlib[shader] p = self.shaderlib[shader]
v, f = self.shaderprograms[shader] v, f = self.shaderprograms[shader]
print("Shader failed to execute: %s" % (shader,)) print(("Shader failed to execute: %s" % (shader,)))
print("Vertex shader log:") print("Vertex shader log:")
lenarr = GLintArray.zeros(1) lenarr = GLintArray.zeros(1)
glGetShaderiv(v, GL_INFO_LOG_LENGTH, lenarr) glGetShaderiv(v, GL_INFO_LOG_LENGTH, lenarr)
infoarr = GLcharArray.zeros(lenarr[0]) infoarr = GLcharArray.zeros(lenarr[0])
outsize = GLsizeiArray.zeros(1) outsize = GLsizeiArray.zeros(1)
glGetShaderInfoLog(v, lenarr[0], outsize, infoarr) glGetShaderInfoLog(v, lenarr[0], outsize, infoarr)
print(''.join([chr(x) for x in infoarr[:outsize[0]]])) print((''.join([chr(x) for x in infoarr[:outsize[0]]])))
print("Fragment shader log:") print("Fragment shader log:")
lenarr = GLintArray.zeros(1) lenarr = GLintArray.zeros(1)
glGetShaderiv(f, GL_INFO_LOG_LENGTH, lenarr) glGetShaderiv(f, GL_INFO_LOG_LENGTH, lenarr)
infoarr = GLcharArray.zeros(lenarr[0]) infoarr = GLcharArray.zeros(lenarr[0])
outsize = GLsizeiArray.zeros(1) outsize = GLsizeiArray.zeros(1)
glGetShaderInfoLog(f, lenarr[0], outsize, infoarr) glGetShaderInfoLog(f, lenarr[0], outsize, infoarr)
print(''.join([chr(x) for x in infoarr[:outsize[0]]])) print((''.join([chr(x) for x in infoarr[:outsize[0]]])))
print("Program info log:") print("Program info log:")
lenarr = GLintArray.zeros(1) lenarr = GLintArray.zeros(1)
glGetProgramiv(p, GL_INFO_LOG_LENGTH, lenarr) glGetProgramiv(p, GL_INFO_LOG_LENGTH, lenarr)
infoarr = GLcharArray.zeros(lenarr[0]) infoarr = GLcharArray.zeros(lenarr[0])
outsize = GLsizeiArray.zeros(1) outsize = GLsizeiArray.zeros(1)
glGetProgramInfoLog(p, lenarr[0], outsize, infoarr) glGetProgramInfoLog(p, lenarr[0], outsize, infoarr)
print(''.join([chr(x) for x in infoarr[:outsize[0]]])) print((''.join([chr(x) for x in infoarr[:outsize[0]]])))
glDeleteShader(v) glDeleteShader(v)
glDeleteShader(f) glDeleteShader(f)
glDeleteProgram(p) glDeleteProgram(p)
@ -215,6 +215,5 @@ class shader_manager(object):
def init(): def init():
global mgr global mgr
mgr = shader_manager() mgr = shader_manager()
print("initiated shader mgr: %s" % (mgr,))
mgr = None mgr = None

526
ui.py Executable file
View file

@ -0,0 +1,526 @@
import enums
from enums import ui_frametype, ui_postype, ui_filltype
from pygame.locals import *
import models
import video
from OpenGL.GL import *
import inputs
class UIFrame(object):
def __init__(self, content, contentdata):
self.func = None
self.content = content
self.data = contentdata
self.parent = None
self.minsize = None
self.maxsize = None
self.size = None
self.gridsize = None
self.pos = None
self.postype = ui_postype.relative
self.posset = None
self.fill = ui_filltype.stretch
self.draggable = False
self.padding = (0, 0)
self.color = None
self.stretchiness = None
def constrain_size(self, x, y):
if self.content == ui_frametype.grid:
x += self.padding[0] * len(self.data) * 2
y += self.padding[1] * len(self.data[0]) * 2
else:
x += self.padding[0] * 2
y += self.padding[1] * 2
if self.minsize:
x = max(self.minsize[0], x)
y = max(self.minsize[1], y)
if self.maxsize:
x = min(self.maxsize[0], x)
y = min(self.maxsize[1], y)
return (x, y)
def get_parent_size(self):
if self.parent == None:
return video.get_res()
else:
#return self.parent.get_child_size(self)
return self.parent.size
def get_child_size(self, child):
if self.content == ui_frametype.grid:
for i, row in enumerate(self.data):
for j, col in enumerate(row):
if col == child:
x = self.gridsize[0][j]
y = self.gridsize[1][i]
if False and self.stretchiness:
xlo = self.size[0] - sum(self.gridsize[0])
ylo = self.size[1] - sum(self.gridsize[1])
if xlo > 0:
xs = self.stretchiness[0][j]
xst = sum(self.stretchiness[0])
x += int(float(xlo) * float(xs) / float(xst))
if ylo > 0:
ys = self.stretchiness[1][i]
yst = sum(self.stretchiness[1])
y += int(float(ylo) * float(ys) / float(yst))
return (x, y)
else:
return self.size
def get_parent_pos(self):
if self.parent == None:
return (0, 0)
else:
#return self.parent.get_child_pos(self)
return self.parent.pos
def get_child_pos(self, child):
if self.content == ui_frametype.grid:
for i, row in enumerate(self.data):
for j, col in enumerate(row):
if col == child:
#x = sum(self.gridsize[0][:j])+self.padding[0]
#y = sum(self.gridsize[1][:i])+self.padding[1]
x = sum(self.gridsize[0][:j])
y = sum(self.gridsize[1][:i])
return (x, y)
else:
return (0, 0)
def autopos(self):
if self.postype == ui_postype.center:
ppos = self.get_parent_pos()
psize = self.get_parent_size()
self.pos = (ppos[0] + (psize[0]//2) - (self.size[0]//2), ppos[1] + (psize[1]//2) - (self.size[1]//2))
elif self.postype == ui_postype.relative:
if not self.posset:
self.posset = self.parent.get_child_pos(self)
ppos = self.get_parent_pos()
psize = self.get_parent_size()
if self.posset[0] >= 0:
x = self.posset[0] + ppos[0]
else:
x = self.posset[0] - ppos[0] - psize[0] + self.size[0]
if self.posset[1] >= 0:
y = self.posset[1] + ppos[1]
else:
y = self.posset[1] - ppos[1] - psize[1] + self.size[1]
self.pos = (x, y)
elif self.postype == ui_postype.absolute:
"This is bad. Don't do this. Asshole."
self.pos = self.posset
alist = [x for x in self.ancestors()]
if mgr.debugobj in alist:
print(("FUCK. OK DUDER. I AM YOUR DEBUG OBJECT: %s" % (alist.index(mgr.debugobj),)))
print((self.parent.pos))
print((self.get_parent_pos()))
print((self.parent.get_child_pos(self)))
#print self.fill == ui_filltype.none
#print self.postype == ui_postype.center
print((self.pos))
#print self.gridsize
print("END DEBUG OBJECT")
"""calculate position top-down, since child's position will depend on having an accurate parent position?"""
for child in self:
child.autopos()
def autosize(self):
if self.content == ui_frametype.model:
self.size = self.constrain_size(int(self.data.get_size()[0]), int(self.data.get_size()[1]))
elif self.content == ui_frametype.grid:
if not self.data:
self.size = self.constrain_size(0, 0)
self.gridsize = [[], []]
return
self.gridsize = [[0] * len(self.data[0]), [0] * len(self.data)]
for ir, row in enumerate(self.data):
for ic, col in enumerate(row):
col.autosize()
self.gridsize[0][ic] = max(self.gridsize[0][ic], col.size[0])
self.gridsize[1][ir] = max(self.gridsize[1][ir], col.size[1])
self.size = self.constrain_size(sum(self.gridsize[0]), sum(self.gridsize[1]))
print(("grid CONSTRAINED: %s - %s" % (self.size, self.padding)))
elif self.content == ui_frametype.composite:
x = 0
y = 0
for child in self:
child.autosize()
x = max(child.size[0], x)
y = max(child.size[1], y)
self.size = self.constrain_size(x, y)
print(("composite CONSTRAINED: %s - %s" % (self.size, self.padding)))
def autofillsize(self):
""" autosize calculates absolute minimum sizes. """
""" autofillsize then pads those as needed (particularly for grid cells) """
if self.parent != None and self.fill != ui_filltype.none and self.postype != ui_postype.center:
self.size = self.parent.get_child_size(self)
if self.fill != ui_filltype.none and self.content == ui_frametype.grid:
print(("Hello I am grid %s, and my size is %s" % (self.gridsize, self.size)))
if self.stretchiness:
for ir, row in enumerate(self.data):
for ic, col in enumerate(row):
xlo = self.size[0] - sum(self.gridsize[0])
ylo = self.size[1] - sum(self.gridsize[1])
print(("Stretching cell %s from %s to %s" % ((ic, ir), self.size, (self.size[0]+xlo, self.size[1]+ylo))))
x = 0
y = 0
if xlo > 0:
xs = self.stretchiness[0][ic]
xst = sum(self.stretchiness[0])
x = int(float(xlo) * float(xs) / float(xst))
if ylo > 0:
ys = self.stretchiness[1][ir]
yst = sum(self.stretchiness[1])
y = int(float(ylo) * float(ys) / float(yst))
self.gridsize[0][ic] += x
self.gridsize[1][ir] += y
for child in self:
child.autofillsize()
def autoparent(self, parent=None):
if parent != None:
#print "Setting parent on %s to %s" % (self, parent)
self.parent = parent
for child in self:
child.autoparent(self)
def auto(self):
self.autoparent()
self.autosize()
self.autofillsize()
self.autopos()
def ancestors(self):
p = self.parent
while True:
if p == None:
raise StopIteration()
yield p
p = p.parent
def __iter__(self):
if self.content == ui_frametype.model:
return
if self.content == ui_frametype.grid:
for row in self.data:
for col in row:
yield col
elif self.content == ui_frametype.composite:
for child in self.data:
yield child
def __len__(self):
if self.content == ui_frametype.model:
return 0
if self.content == ui_frametype.grid:
if len(self.data) == 0:
return 0
return len(self.data) * len(self.data[0])
elif self.content == ui_frametype.composite:
return len(self.data)
def handle_keypress(self, ev):
return False
def handle_event(self, ev):
for child in self:
handled = child.handle_event(ev)
if handled:
return True
if self.relevant_event(ev):
if ev.type == MOUSEBUTTONDOWN:
self.set_focus()
if self.draggable:
self.drag_offset = (self.pos[0] - ev.pos[0], self.pos[1] - ev.pos[1])
for p in self.ancestors():
pass
p
mgr.drag_hook = p.move_drag
elif ev.type == MOUSEBUTTONUP:
if mgr.mousedown:
#print "Mouseclick detected... %s %s ------ %s %s" % (mgr.mousedown, mgr.mousedown.pos if mgr.mousedown else None, self.contains_pos(mgr.mousedown.pos), self.func)
if self.contains_pos(mgr.mousedown.pos):
""" welp, this is a valid click -- down was inside us, and so is up """
if self.func != None:
self.func(ev)
return True
elif ev.type == KEYUP:
if self.is_focus():
return self.handle_keypress(ev)
elif ev.type == VIDEORESIZE:
if self.parent == None:
self.autosize()
self.autopos()
return False
def convert_coords(self, pos, postype, newtype):
if postype == newtype:
return pos
ppos = self.get_parent_pos()
psize = self.get_parent_size()
anchorx = False
anchory = False
if postype == ui_postype.relative:
if pos[0] >= 0:
x = pos[0] + ppos[0]
else:
x = pos[0] + ppos[0] + psize[0] - self.size[0]
if pos[1] >= 0:
y = pos[1] + ppos[1]
else:
y = pos[1] + ppos[1] + psize[1] - self.size[1]
pos = (x, y)
elif postype == ui_postype.center:
pos = (ppos[0] + (psize[0]//2) - (self.size[0]//2), ppos[1] + (psize[1]//2) - (self.size[1]//2))
if newtype == ui_postype.center:
pos = (ppos[0] + (psize[0]//2) - (self.size[0]//2), ppos[1] + (psize[1]//2) - (self.size[1]//2))
elif newtype == ui_postype.relative:
if self.posset[0] >= 0:
x = pos[0] - ppos[0]
else:
x = pos[0] - ppos[0] - psize[0] + self.size[0]
if self.posset[1] >= 0:
y = pos[1] - ppos[1]
else:
y = pos[1] - ppos[1] - psize[1] + self.size[1]
elif newtype == ui_postype.absolute:
pass
return pos
def move_drag(self, ev):
newpos = (ev.pos[0] + self.drag_offset[0], ev.pos[1] + self.drag_offset[1])
rel_newpos = self.convert_coords(pos, ui_postype.absolute, self.postype)
self.posset = rel_newpos
self.autopos()
def contains_pos(self, pos):
if pos[0] >= self.pos[0] and pos[0] < (self.pos[0] + self.size[0]):
if pos[1] >= self.pos[1] and pos[1] < (self.pos[1] + self.size[1]):
return True
return False
def relevant_event(self, ev):
if ev.type == MOUSEMOTION:
return self.contains_pos(ev.pos)
elif ev.type == MOUSEBUTTONDOWN:
return self.contains_pos(ev.pos)
elif ev.type == MOUSEBUTTONUP:
return self.contains_pos(ev.pos)
elif ev.type == KEYDOWN:
return self.is_focus()
elif ev.type == KEYUP:
return self.is_focus()
else:
return True
def is_focus(self):
return mgr.focus == self
def set_focus(self):
mgr.set_focus(self)
def render(self):
for child in self:
child.render()
if self.content == ui_frametype.model:
if mgr.debug < 0:
mgr.debug += 1
if isinstance(self.data, models.TextModel):
print(("%s - %s - TEXT %s" % (self.pos, self.size, self.data.text)))
else:
for l in self.data.layers:
print(("%s - %s - %s" % (self.pos, self.size, l.material.id)))
glPushMatrix()
if isinstance(self.data, models.TextModel):
glTranslate(self.pos[0], self.pos[1], 10.0)
else:
glTranslate(float(self.pos[0]) + (float(self.size[0]) / 2.0), float(self.pos[1]) + (float(self.size[1]) / 2.0), 10.0)
newscale = [float(self.size[0]), float(self.size[1]), 1.0]
for layer in self.data.layers:
#if newscale != layer.scale:
# print "Changing scale on %s %s from %s to %s" % (layer.material.id, self.size, layer.scale, newscale)
layer.scale = newscale
#if "_bg_" in layer.material.id:
#layer.color = self.color
self.data.render()
glPopMatrix()
def make_box(sprite, center, color):
l = [['tl', 'tc', 'tr'], ['cl', 'cc', 'cr'], ['bl', 'bc', 'br']]
for i, r in enumerate(l):
for j, c in enumerate(r):
mdl = models.mgr.create("%s_%s" % (sprite, c))
l[i][j] = UIFrame(ui_frametype.model, mdl)
#if len(mdl.layers) > 1:
mdl.layers[-1].color = color
if c == 'cc':
l[i][j] = UIFrame(ui_frametype.composite, [l[i][j], center])
elif 'c' in c:
"""Border edges should be repeated to fill!"""
l[i][j].fill = ui_filltype.tile
#l[i] = tuple(l[i])
#l = tuple(l)
uf = UIFrame(ui_frametype.grid, l)
uf.stretchiness = [[0, 1, 0], [0, 1, 0]]
return uf
def make_button(text, clickfunc):
text = models.TextModel("micross20", text)
textframe = UIFrame(ui_frametype.model, text)
textframe.postype = ui_postype.center
btnframe = make_box("ui_button", textframe, (0.3, 0.3, 1.0, 1.0))
btnframe.func = clickfunc
return btnframe
def startgame(ev):
mgr.remove("mainmenu")
def clicktest(ev):
print("I'm an event!")
def exitgame(ev):
inputs.add_command('exit')
def make_mainmenu():
b1 = make_button("Start", startgame)
b2 = make_button("Options", clicktest)
b3 = make_button("Exit", exitgame)
b1.padding = (20,0)
b2.padding = (20,0)
b3.padding = (20,0)
buttongrid = UIFrame(ui_frametype.grid, [[b1], [b2], [b3]])
buttongrid.postype = ui_postype.center
buttongrid.fill = ui_filltype.stretch
buttongrid.stretchiness = [[1], [1, 1, 1]]
mgr.debugobj = b1
buttongrid = UIFrame(ui_frametype.composite, [buttongrid])
buttongrid.padding = (20, 30)
mainframe = make_box("ui_frame", buttongrid, (0.0, 0.0, 1.0, 0.35))
mainframe.postype = ui_postype.center
return mainframe
class UIManager(object):
def __init__(self):
self.frames = []
self.framenames = {}
self.focus = None
self.last_mousedown = None
self.mousemove_hook = None
self.debug = 0
def set_focus(self, frame):
self.focus = frame
def add(self, frame, name):
assert name not in self.framenames
self.framenames[name] = frame
frame.index = len(self.frames)
frame.auto()
print((frame.pos))
for child in frame:
print(("%s-%s" % (child.pos, child.size)))
"""
print "Ok"
print frame.data[1][1].data[1].gridsize
btngrid = frame.data[1][1].data[1]
btn3 = btngrid.data[2][0]
print "btn3"
print btn3.pos
print btngrid.get_child_pos(btn3)
"""
self.frames.append(frame)
def remove(self, frame):
fdel = self.framenames[frame]
for i, f in enumerate(self.frames):
if f is fdel:
del self.frames[i]
def render(self):
for frame in self.frames:
frame.render()
def handle_event(self, ev):
if ev.type == MOUSEMOTION and self.mousemove_hook != None:
self.drag_hook(ev)
return True
handled = False
for fr in self.frames:
handled = fr.handle_event(ev)
if handled:
break
if not handled:
self.set_focus(None)
if ev.type == MOUSEBUTTONDOWN:
print(("MOUSECLICK: %s" % (ev.pos,)))
self.mousedown = ev
if ev.type == MOUSEBUTTONUP:
self.drag_hook = None
self.mousedown = None
mgr = UIManager()