From 65019a5e43dfbd0933b4d491c40708be2a4dddee Mon Sep 17 00:00:00 2001 From: cecilkorik Date: Mon, 8 May 2017 23:17:52 -0700 Subject: [PATCH] Integrated major improvements from shooter2 project, including slick UI module! --- .hgignore | 6 +- __init__.py | 2 +- data/ui/button_bg_corner.png | Bin 0 -> 2822 bytes data/ui/button_bg_edge.png | Bin 0 -> 2802 bytes data/ui/button_corner.png | Bin 0 -> 2810 bytes data/ui/button_edge.png | Bin 0 -> 2798 bytes data/ui/frame_bg_corner.png | Bin 0 -> 2814 bytes data/ui/frame_bg_edge.png | Bin 0 -> 2797 bytes data/ui/frame_corner.png | Bin 0 -> 2854 bytes data/ui/frame_edge.png | Bin 0 -> 2813 bytes data/xml/constants.xml | 4 +- data/xml/def/models.xml | 6 + data/xml/models.xml | 185 +++++++++++- data/xml/textures.xml | 52 +++- enums.py | 24 +- fonts.py | 9 +- gameobj.py | 13 + gametimer.py | 188 ++++++------- models.py | 68 ++++- roc_core.py | 8 +- universe.py => roc_engine.py | 4 +- roc_main.py | 16 +- roc_test.py | 5 +- shader.py | 15 +- ui.py | 526 +++++++++++++++++++++++++++++++++++ 25 files changed, 991 insertions(+), 140 deletions(-) create mode 100755 data/ui/button_bg_corner.png create mode 100755 data/ui/button_bg_edge.png create mode 100755 data/ui/button_corner.png create mode 100755 data/ui/button_edge.png create mode 100755 data/ui/frame_bg_corner.png create mode 100755 data/ui/frame_bg_edge.png create mode 100755 data/ui/frame_corner.png create mode 100755 data/ui/frame_edge.png rename universe.py => roc_engine.py (83%) create mode 100755 ui.py 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 0000000000000000000000000000000000000000..ed0aaa758095393977fd1ea256accaaaacae9cdb GIT binary patch literal 2822 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 Y0HksYr<-8wb^rhX07*qoM6N<$f`eT-*Z=?k literal 0 HcmV?d00001 diff --git a/data/ui/button_bg_edge.png b/data/ui/button_bg_edge.png new file mode 100755 index 0000000000000000000000000000000000000000..aa550e81afd8cc3149a15caeff840502666b24a2 GIT binary patch literal 2802 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 Ef^FwA=Kufz literal 0 HcmV?d00001 diff --git a/data/ui/button_corner.png b/data/ui/button_corner.png new file mode 100755 index 0000000000000000000000000000000000000000..ad04941359d7eee28da3a13df9da8b46593af5f6 GIT binary patch literal 2810 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 Ef`}zZn*aa+ literal 0 HcmV?d00001 diff --git a/data/ui/frame_edge.png b/data/ui/frame_edge.png new file mode 100755 index 0000000000000000000000000000000000000000..f2500d341730ceffc2e6c3a485bbad0ad7f22cf2 GIT binary patch literal 2813 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 z0000eNklo literal 0 HcmV?d00001 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() +