diff --git a/.hgignore b/.hgignore
index 280123e..3d5fd1f 100644
--- a/.hgignore
+++ b/.hgignore
@@ -1,6 +1,6 @@
-syntax: glob
-*.pyc
-settings.cfg
+syntax: glob
+*.pyc
+settings.cfg
lib
bin
include
diff --git a/__init__.py b/__init__.py
index 0f2d8f8..6a72088 100755
--- a/__init__.py
+++ b/__init__.py
@@ -1,5 +1,5 @@
from roc_core import *
-import universe
+import roc_engine
import pipeline
import inputs
import physics
diff --git a/data/ui/button_bg_corner.png b/data/ui/button_bg_corner.png
new file mode 100755
index 0000000..ed0aaa7
Binary files /dev/null and b/data/ui/button_bg_corner.png differ
diff --git a/data/ui/button_bg_edge.png b/data/ui/button_bg_edge.png
new file mode 100755
index 0000000..aa550e8
Binary files /dev/null and b/data/ui/button_bg_edge.png differ
diff --git a/data/ui/button_corner.png b/data/ui/button_corner.png
new file mode 100755
index 0000000..ad04941
Binary files /dev/null and b/data/ui/button_corner.png differ
diff --git a/data/ui/button_edge.png b/data/ui/button_edge.png
new file mode 100755
index 0000000..2eca13b
Binary files /dev/null and b/data/ui/button_edge.png differ
diff --git a/data/ui/frame_bg_corner.png b/data/ui/frame_bg_corner.png
new file mode 100755
index 0000000..97ff535
Binary files /dev/null and b/data/ui/frame_bg_corner.png differ
diff --git a/data/ui/frame_bg_edge.png b/data/ui/frame_bg_edge.png
new file mode 100755
index 0000000..16f5ba2
Binary files /dev/null and b/data/ui/frame_bg_edge.png differ
diff --git a/data/ui/frame_corner.png b/data/ui/frame_corner.png
new file mode 100755
index 0000000..ab12886
Binary files /dev/null and b/data/ui/frame_corner.png differ
diff --git a/data/ui/frame_edge.png b/data/ui/frame_edge.png
new file mode 100755
index 0000000..f2500d3
Binary files /dev/null and b/data/ui/frame_edge.png differ
diff --git a/data/xml/constants.xml b/data/xml/constants.xml
index 4b97529..836de95 100644
--- a/data/xml/constants.xml
+++ b/data/xml/constants.xml
@@ -1,6 +1,6 @@
-
-
+
diff --git a/data/xml/def/models.xml b/data/xml/def/models.xml
index fd39876..7df099c 100755
--- a/data/xml/def/models.xml
+++ b/data/xml/def/models.xml
@@ -19,6 +19,12 @@
+
+
+
+
+
+
diff --git a/data/xml/models.xml b/data/xml/models.xml
index 00e461e..0e24d86 100755
--- a/data/xml/models.xml
+++ b/data/xml/models.xml
@@ -1,10 +1,14 @@
-
+
+
+
+
+
[mesh_sprite]
@@ -31,10 +35,187 @@
- [mesh_centered_sprite]
+ [mesh_centered_sprite]
[mat_dralthi]
+
+
+
+ [mesh_sprite]
+ [mat_ui_frame_corner]
+
+
+ [mesh_sprite]
+ [mat_ui_frame_bg_corner]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_frame_edge]
+
+
+ [mesh_sprite]
+ [mat_ui_frame_bg_edge]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_frame_corner]
+
+
+ [mesh_sprite]
+ [mat_ui_frame_bg_corner]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_frame_edge]
+
+
+ [mesh_sprite]
+ [mat_ui_frame_bg_edge]
+
+
+
+
+ [mesh_sprite]
+ [mat_blank]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_frame_edge]
+
+
+ [mesh_sprite]
+ [mat_ui_frame_bg_edge]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_frame_corner]
+
+
+ [mesh_sprite]
+ [mat_ui_frame_bg_corner]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_frame_edge]
+
+
+ [mesh_sprite]
+ [mat_ui_frame_bg_edge]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_frame_corner]
+
+
+ [mesh_sprite]
+ [mat_ui_frame_bg_corner]
+
+
+
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_button_corner]
+
+
+ [mesh_sprite]
+ [mat_ui_button_bg_corner]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_button_edge]
+
+
+ [mesh_sprite]
+ [mat_ui_button_bg_edge]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_button_corner]
+
+
+ [mesh_sprite]
+ [mat_ui_button_bg_corner]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_button_edge]
+
+
+ [mesh_sprite]
+ [mat_ui_button_bg_edge]
+
+
+
+
+ [mesh_sprite]
+ [mat_blank]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_button_edge]
+
+
+ [mesh_sprite]
+ [mat_ui_button_bg_edge]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_button_corner]
+
+
+ [mesh_sprite]
+ [mat_ui_button_bg_corner]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_button_edge]
+
+
+ [mesh_sprite]
+ [mat_ui_button_bg_edge]
+
+
+
+
+ [mesh_sprite]
+ [mat_ui_button_corner]
+
+
+ [mesh_sprite]
+ [mat_ui_button_bg_corner]
+
+
+
diff --git a/data/xml/textures.xml b/data/xml/textures.xml
index e91258d..d041dac 100755
--- a/data/xml/textures.xml
+++ b/data/xml/textures.xml
@@ -13,7 +13,7 @@
-
+
@@ -28,6 +28,56 @@
tex/dralthi.png
+
+
+
+ ui/button_corner.png
+
+
+ ui/button_edge.png
+
+
+ ui/button_bg_corner.png
+
+
+ ui/button_bg_edge.png
+
+
+ ui/frame_corner.png
+
+
+ ui/frame_edge.png
+
+
+ ui/frame_bg_corner.png
+
+
+ ui/frame_bg_edge.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
tex/plasma1.png
diff --git a/enums.py b/enums.py
index a733ca4..dd02c27 100755
--- a/enums.py
+++ b/enums.py
@@ -1,5 +1,9 @@
class enum(object):
+ def __init__(self, names=[]):
+ for i, name in enumerate(names):
+ setattr(self, name, i)
+
def __len__(self):
return len([x for x in dir(self) if x[0] != '_'])
@@ -82,4 +86,22 @@ tt = enum()
tt.diffuse = 0 # the diffuse texture sets the colors and general brightness of the texture. if the same texture is used as the emissive texture, the model is effectively "fullbright"
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.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)
\ No newline at end of file
+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
+
diff --git a/fonts.py b/fonts.py
index b6ec973..53f356c 100644
--- a/fonts.py
+++ b/fonts.py
@@ -100,7 +100,14 @@ class TexFont(object):
else:
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):
"""
diff --git a/gameobj.py b/gameobj.py
index ba44292..50c3ff4 100755
--- a/gameobj.py
+++ b/gameobj.py
@@ -1,5 +1,18 @@
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):
def __init__(self, self.pos):
self.pos = pos
diff --git a/gametimer.py b/gametimer.py
index 0a8fcc8..7bd6a80 100755
--- a/gametimer.py
+++ b/gametimer.py
@@ -1,104 +1,98 @@
import pygame
import collections
-def start_loop():
- global g_timer, g_elapsed
- g_elapsed = 0
- g_elapsed_sec = 0.0
- g_timer = pygame.time.get_ticks()
- reset_fps_count()
-
-def next_frame(skipping=False):
- global g_timer, g_elapsed, g_elapsed_sec
-
- newticks = pygame.time.get_ticks()
- #if skipping:
- # # reset g_timer to it's value from the previous frame
- # g_timer -= g_elapsed
- g_elapsed = newticks - g_timer
- g_timer = newticks
- g_elapsed_sec = float(g_elapsed) / 1000.0
-
- if g_elapsed != 0:
- update_fps_count(g_elapsed)
-
-
-def reset_fps_count():
- global g_framelist, update_fps_count
- g_framelist = collections.deque()
- update_fps_count = update_fps_count_empty
-
-def update_fps_count_empty(elapsed):
- global g_framelist, update_fps_count
- g_framelist.append(elapsed)
- if len(g_framelist) >= 25:
- update_fps_count = update_fps_count_full
-
-def update_fps_count_full(elapsed):
- global g_framelist
- g_framelist.popleft()
- 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():
- """
- get the amount of time in milliseconds passed since the last frame was displayed
- """
- return g_elapsed
-
-def elapsed_sec():
- """
- get the amount of time in seconds passed since the last frame was displayed
- """
- return g_elapsed_sec
-
-def num_frames(delay, offset=0):
- """
- if you want something to occur every "delay" milliseconds,
- this will return the number of times you should make it happen
- in this particular frame (can be 0)
- """
- global g_elapsed, g_timer
- return int((g_timer - offset) / delay) - int((g_timer - g_elapsed - offset) / delay)
-
-def loop_frames(delay, offset=0):
- return range(num_frames(delay, offset))
-
-def get_timer():
- return g_timer
-
-def average(d):
- #spf = (float(sum(g_framelist)) / (len(g_framelist) * 1000.0))
- if len(d) == 0:
- return 0.0
-
- smooth = 0.85
- #v2 = float(d[-1])
- #for i in xrange(len(d) - 2, 0, -1):
- # pass
+class GameTimer(object):
+ def __init__(self):
+ self.update_fps_count = None
+
+ def start_loop(self):
+ 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()
+ #if skipping:
+ # # reset self.timer to it's value from the previous frame
+ # self.timer -= self.elapsed
+ self.elapsed = newticks - self.timer
+ self.timer = newticks
+ self.elapsed_sec = float(self.elapsed) / 1000.0
+
+ if self.elapsed != 0:
+ self.update_fps_count(self.elapsed)
+
+
+ def reset_fps_count(self):
+ self.framelist = collections.deque()
+ self.update_fps_count = self.update_fps_count_empty
+
+ def update_fps_count_empty(self, elapsed):
+ self.framelist.append(elapsed)
+ if len(self.framelist) >= 25:
+ self.update_fps_count = self.update_fps_count_full
+
+ def update_fps_count_full(self, elapsed):
+ self.framelist.popleft()
+ self.framelist.append(elapsed)
+
+
+ def elapsed(self):
+ """
+ get the amount of time in milliseconds passed since the last frame was displayed
+ """
+ return self.elapsed
+
+ def elapsed_sec(self):
+ """
+ get the amount of time in seconds passed since the last frame was displayed
+ """
+ return self.elapsed_sec
+
+ def num_frames(self, delay, offset=0):
+ """
+ if you want something to occur every "delay" milliseconds,
+ this will return the number of times you should make it happen
+ in this particular frame (can be 0)
+ """
+ return int((self.timer - offset) / delay) - int((self.timer - self.elapsed - offset) / delay)
+
+ def loop_frames(self, delay, offset=0):
+ return range(num_frames(delay, offset))
+
+ def get_timer(self):
+ return self.timer
+
+ def average(self, d):
+ #spf = (float(sum(self.framelist)) / (len(self.framelist) * 1000.0))
+ if len(d) == 0:
+ return 0.0
+
+ smooth = 0.85
+ #v2 = float(d[-1])
+ #for i in xrange(len(d) - 2, 0, -1):
+ # pass
+
+ v2 = float(d[0])
+ for i in range(1, len(d)):
+ v1 = float(d[i])
+ v2 = (smooth * v2) + ((1.0 - smooth) * v1)
+
+ return v2
+
+
+ def get_fps(self):
+ #return ",".join([str(x) for x in sorted(self.framelist)])
+ if len(self.framelist) == 0.0:
+ return 0.0
+ spf = self.average(self.framelist) / 1000.0
+ if spf == 0.0:
+ return 0.0
+ #print "%s < %s" % (1.0 / spf, self.framelist)
+ return 1.0 / spf
- v2 = float(d[0])
- for i in range(1, len(d)):
- v1 = float(d[i])
- v2 = (smooth * v2) + ((1.0 - smooth) * v1)
-
- return v2
-
-
-def get_fps():
- global g_framelist
- #return ",".join([str(x) for x in sorted(g_framelist)])
- if len(g_framelist) == 0.0:
- return 0.0
- spf = average(g_framelist) / 1000.0
- if spf == 0.0:
- return 0.0
- #print "%s < %s" % (1.0 / spf, g_framelist)
- return 1.0 / spf
-
diff --git a/models.py b/models.py
index 60a7c94..23c9dc3 100755
--- a/models.py
+++ b/models.py
@@ -46,7 +46,9 @@ class Model_Manager(object):
def load_textypes(self):
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.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.specular] = TextureType(GL_TEXTURE2, GL_TEXTURE_2D)
self.textypes[enums.tt.normal] = TextureType(GL_TEXTURE3, GL_TEXTURE_2D)
@@ -97,7 +99,8 @@ class Model_Manager(object):
self.models = {}
for meshdata in mdldata.mesh:
if meshdata['sprite']:
- self.sprite_mesh = SpriteMesh()
+ if self.sprite_mesh == None:
+ self.sprite_mesh = SpriteMesh()
mesh = self.sprite_mesh
elif meshdata['centered_sprite']:
if self.centered_sprite_mesh == None:
@@ -266,14 +269,22 @@ class Material(object):
if texobj.uniform:
if self.texcoords_uniform == self.texcoords_notimpl:
self.texcoords_uniform = texobj.texcoords
+ self.texcoords = texobj.texcoords
else:
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)
if self.texcoords == self.texcoords_notimpl:
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):
@@ -333,6 +344,12 @@ class SpriteMeshCentered(SpriteMesh):
Vertex(vect(-0.5, 0.5, 0.0), vect(0.0, 0.0, 1.0), (0.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):
def __init__(self, layernum):
@@ -343,6 +360,8 @@ class RenderLayer(object):
self.scale = [1.0, 1.0, 1.0]
self.displaylist = None
self.anim = "idle"
+ self.rotations = None
+ self.tile = False
def load(self, layerdata):
meshdata = layerdata.mesh
@@ -352,23 +371,46 @@ class RenderLayer(object):
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 = [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):
self.material.bind()
glPushMatrix()
glScalef(*self.scale)
if self.color != None:
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:
self.displaylist = glGenLists(1)
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()
#print "Drawing mesh %s" % ( self.displaylist, )
glCallList(self.displaylist)
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):
def __init__(self, layernum):
@@ -383,6 +425,15 @@ class Model(object):
def __init__(self):
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):
tmplayers = []
for rend in data.render:
@@ -404,6 +455,7 @@ class Model(object):
class TextModel(Model):
def __init__(self, fontname, text, color=None, scale=None):
+ Model.__init__(self)
self.displaylist = None
self.fontname = fontname
self.text = text
@@ -418,6 +470,10 @@ class TextModel(Model):
def instance(self):
return self
+ def get_size(self):
+ font = mgr.get_font(self.fontname)
+ return font.get_size(self.text)
+
def render(self):
glPushMatrix()
glScalef(*self.scale)
diff --git a/roc_core.py b/roc_core.py
index 8165341..b6f6c6e 100755
--- a/roc_core.py
+++ b/roc_core.py
@@ -4,9 +4,9 @@ import video
import shader
import models
import roc_main
-import universe
+import roc_engine
import config
-base_universe = universe.base_universe
+base_engine = roc_engine.base_engine
def init2d():
init(videoinit=video.init2d)
@@ -29,8 +29,8 @@ def init(videoinit):
models.init()
-def set_universe(new_universe):
- roc_main.set_universe(new_universe)
+def set_engine(new_engine):
+ roc_main.set_engine(new_engine)
def main():
roc_main.mainloop()
diff --git a/universe.py b/roc_engine.py
similarity index 83%
rename from universe.py
rename to roc_engine.py
index 5056682..571854b 100755
--- a/universe.py
+++ b/roc_engine.py
@@ -4,7 +4,7 @@ import pygame
from OpenGL.GL import *
from py3dutil import vect, quat
-class base_universe(object):
+class base_engine(object):
def __init__(self):
pass
@@ -20,7 +20,7 @@ class base_universe(object):
def render(self):
pass
-class tiled_universe(base_universe):
+class tiled_engine(base_engine):
def __init__(self):
pass
diff --git a/roc_main.py b/roc_main.py
index 5cf4323..d1c91ea 100755
--- a/roc_main.py
+++ b/roc_main.py
@@ -10,20 +10,18 @@ import config
from OpenGL.GL import *
-def set_universe(new_universe):
- global g_universe
- g_universe = new_universe
+def set_engine(new_engine):
+ global g_engine
+ g_engine = new_engine
-g_universe = None
+g_engine = None
def mainloop():
- global g_universe
+ global g_engine
- gametimer.start_loop()
while True:
events = pygame.event.get()
- gametimer.next_frame()
pygame.event.pump()
for ev in events:
if ev.type == QUIT:
@@ -42,9 +40,9 @@ def mainloop():
video.predraw()
- g_universe.frame(events)
+ g_engine.frame(events)
video.next_frame()
video.save_window_pos()
- config.mgr.save()
\ No newline at end of file
+ config.mgr.save()
diff --git a/roc_test.py b/roc_test.py
index c901d54..7c3af9a 100755
--- a/roc_test.py
+++ b/roc_test.py
@@ -1,7 +1,6 @@
#import roc
import os
import sys
-sys.path.append(os.path.abspath('..'))
import roc
import pygame
from OpenGL.GL import *
@@ -60,7 +59,7 @@ class partycle(object):
self.yd *= 0.985
self.rot += self.rotd
-class test_universe(roc.universe.base_universe):
+class test_engine(roc.engine.base_engine):
def __init__(self):
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))
@@ -168,7 +167,7 @@ class test_universe(roc.universe.base_universe):
roc.video.width = 1024
roc.video.height = 768
roc.init2d()
-roc.set_universe(test_universe())
+roc.set_engine(test_engine())
roc.main()
diff --git a/shader.py b/shader.py
index b2ec4fe..7f9eb39 100755
--- a/shader.py
+++ b/shader.py
@@ -122,17 +122,17 @@ class shader_manager(object):
try:
shaderinit()
except:
- print("Shader type %s failed to initialize" % (shadername,))
+ print(("Shader type %s failed to initialize" % (shadername,)))
continue
try:
self.select("ffp")
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
try:
self.select("standard")
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
workable_shaders.append(shadername)
@@ -171,28 +171,28 @@ class shader_manager(object):
except GLError:
p = self.shaderlib[shader]
v, f = self.shaderprograms[shader]
- print("Shader failed to execute: %s" % (shader,))
+ print(("Shader failed to execute: %s" % (shader,)))
print("Vertex shader log:")
lenarr = GLintArray.zeros(1)
glGetShaderiv(v, GL_INFO_LOG_LENGTH, lenarr)
infoarr = GLcharArray.zeros(lenarr[0])
outsize = GLsizeiArray.zeros(1)
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:")
lenarr = GLintArray.zeros(1)
glGetShaderiv(f, GL_INFO_LOG_LENGTH, lenarr)
infoarr = GLcharArray.zeros(lenarr[0])
outsize = GLsizeiArray.zeros(1)
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:")
lenarr = GLintArray.zeros(1)
glGetProgramiv(p, GL_INFO_LOG_LENGTH, lenarr)
infoarr = GLcharArray.zeros(lenarr[0])
outsize = GLsizeiArray.zeros(1)
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(f)
glDeleteProgram(p)
@@ -215,6 +215,5 @@ class shader_manager(object):
def init():
global mgr
mgr = shader_manager()
- print("initiated shader mgr: %s" % (mgr,))
mgr = None
diff --git a/ui.py b/ui.py
new file mode 100755
index 0000000..60b7d0e
--- /dev/null
+++ b/ui.py
@@ -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()
+