mostly finished conversion of roc to importable module

improved ui component further, now capable of importing UI layouts from xml data files
This commit is contained in:
cecilkorik 2017-05-16 03:04:42 -04:00
parent bcd74e64c5
commit 6e691bed7b
18 changed files with 519 additions and 152 deletions

View file

@ -1,15 +1,15 @@
from roc_core import *
import roc_engine
import pipeline
import inputs
import physics
import models
import gamedata
import enums
import files
import gametimer
import shader
import video
from .roc_core import *
from . import roc_engine
from . import pipeline
from . import inputs
from . import physics
from . import models
from . import gamedata
from . import enums
from . import files
from . import gametimer
from . import shader
from . import video
#from .universe import *
#from .pipeline import *

View file

@ -3,7 +3,7 @@ import math
from quat import *
from py3dutil import vect
from OpenGL.GL import *
import files
from . import files
class game_camera(game_object):
def __init__(self):

View file

@ -1,5 +1,5 @@
import os
import files
from . import files
class configmanager(object):
def __init__(self):

116
roc/depgraph.py Normal file
View file

@ -0,0 +1,116 @@
class CircularReferenceInternal(ValueError):
def __init__(self, msg, node):
super(CircularReferenceInternal, self).__init__(self, msg)
self.node = node
class CircularReferenceError(ValueError):
pass
class DepGraph(object):
def __init__(self):
self.graph = []
self.reference_map = {}
self.resolving_map = {}
self.resolved_map = {}
self.resolution = []
self.resolving = []
def add(self, ident, deps):
dgn = (ident, deps)
self.graph.append(dgn)
self.reference_map[ident] = dgn
def resolve_node(self, node):
self.resolving.append(node[0])
if node[0] in self.resolving_map:
raise CircularReferenceInternal("Circular reference", node[0])
if node[0] in self.resolved_map:
#print("already resolved")
return
self.resolving_map[node[0]] = 1
if node[1]:
for dep in node[1]:
self.resolve_node(self.reference_map[dep])
self.resolution.append(node[0])
self.resolved_map[node[0]] = node
def resolve(self):
self.resolved_map = {}
self.resolution = []
for g in self.graph:
self.resolving_map = {}
self.resolving = []
err = None
try:
self.resolve_node(g)
except CircularReferenceInternal:
circ = []
for v in reversed(self.resolving):
if v in self.resolved_map:
continue
if v == self.resolving[-1]:
break
circ.append(v)
err = CircularReferenceError("Circular reference detected between %s" % (tuple(circ),))
if err:
raise err
def bottomup_iter(self):
return self.resolution
if __name__ == "__main__":
dg = DepGraph()
dg.add("a", ["d", "c"])
dg.add("b", ["c"])
dg.add("d", [])
dg.add("c", [])
dg.resolve()
print(list(dg.bottomup_iter()))
dg = DepGraph()
dg.add("a", ["d", "c"])
dg.add("b", ["c"])
dg.add("d", [])
dg.add("e", [])
dg.add("f", ["e"])
dg.add("ko", ["f"])
dg.add("j", [])
dg.add("d", [])
dg.add("c", [])
dg.resolve()
print(list(dg.bottomup_iter()))
try:
dg = DepGraph()
dg.add("a", ["d", "c"])
dg.add("b", ["c"])
dg.add("d", [])
dg.add("c", ["j"])
dg.resolve()
print(list(dg.bottomup_iter()))
except:
print("error (as expected)")
dg = DepGraph()
dg.add("a", ["d", "c"])
dg.add("b", ["c"])
dg.add("d", [])
dg.add("c", ["d"])
dg.resolve()
print(list(dg.bottomup_iter()))

View file

@ -4,9 +4,9 @@ try:
from xml.etree.cElementTree import parse
except ImportError:
from elementtree.ElementTree import parse
import files
import shader
from deprecate import deprecated
from . import files
from . import shader
from .deprecate import deprecated
class MissingNode(object):
def __init__(self):
@ -178,7 +178,7 @@ class XMLGameDataReader(object):
for child in xml.getchildren():
if not child.tag in tagdict:
raise ValueError
raise ValueError("Unrecognized tag %s" % (child.tag,))
continue
binchild = tagdict[child.tag]
xmlchild = child

View file

@ -1,5 +1,5 @@
from pygame.locals import *
import video
from . import video
state = {}
commands = {}

40
roc/lua.py Normal file
View file

@ -0,0 +1,40 @@
import lupa
sandbox = """
function sandbox_enter(func)
sandbox_env = {
ipairs = ipairs,
next = next,
pairs = pairs,
pcall = pcall,
tonumber = tonumber,
tostring = tostring,
type = type,
unpack = unpack,
coroutine = { create = coroutine.create, resume = coroutine.resume,
running = coroutine.running, status = coroutine.status,
wrap = coroutine.wrap },
string = { byte = string.byte, char = string.char, find = string.find,
format = string.format, gmatch = string.gmatch, gsub = string.gsub,
len = string.len, lower = string.lower, match = string.match,
rep = string.rep, reverse = string.reverse, sub = string.sub,
upper = string.upper },
table = { insert = table.insert, maxn = table.maxn, remove = table.remove,
sort = table.sort },
math = { abs = math.abs, acos = math.acos, asin = math.asin,
atan = math.atan, atan2 = math.atan2, ceil = math.ceil, cos = math.cos,
cosh = math.cosh, deg = math.deg, exp = math.exp, floor = math.floor,
fmod = math.fmod, frexp = math.frexp, huge = math.huge,
ldexp = math.ldexp, log = math.log, log10 = math.log10, max = math.max,
min = math.min, modf = math.modf, pi = math.pi, pow = math.pow,
rad = math.rad, random = math.random, sin = math.sin, sinh = math.sinh,
sqrt = math.sqrt, tan = math.tan, tanh = math.tanh },
os = { clock = os.clock, difftime = os.difftime, time = os.time },
}
setfenv(func, sandbox_env)
return pcall(func)
end
"""

40
roc/lupa_sandbox.py Normal file
View file

@ -0,0 +1,40 @@
import lupa
sandbox = """
function sandbox_enter(func)
sandbox_env = {
ipairs = ipairs,
next = next,
pairs = pairs,
pcall = pcall,
tonumber = tonumber,
tostring = tostring,
type = type,
unpack = unpack,
coroutine = { create = coroutine.create, resume = coroutine.resume,
running = coroutine.running, status = coroutine.status,
wrap = coroutine.wrap },
string = { byte = string.byte, char = string.char, find = string.find,
format = string.format, gmatch = string.gmatch, gsub = string.gsub,
len = string.len, lower = string.lower, match = string.match,
rep = string.rep, reverse = string.reverse, sub = string.sub,
upper = string.upper },
table = { insert = table.insert, maxn = table.maxn, remove = table.remove,
sort = table.sort },
math = { abs = math.abs, acos = math.acos, asin = math.asin,
atan = math.atan, atan2 = math.atan2, ceil = math.ceil, cos = math.cos,
cosh = math.cosh, deg = math.deg, exp = math.exp, floor = math.floor,
fmod = math.fmod, frexp = math.frexp, huge = math.huge,
ldexp = math.ldexp, log = math.log, log10 = math.log10, max = math.max,
min = math.min, modf = math.modf, pi = math.pi, pow = math.pow,
rad = math.rad, random = math.random, sin = math.sin, sinh = math.sinh,
sqrt = math.sqrt, tan = math.tan, tanh = math.tanh },
os = { clock = os.clock, difftime = os.difftime, time = os.time },
}
setfenv(func, sandbox_env)
return pcall(func)
end
"""

View file

@ -1,12 +1,12 @@
import os
import glob
import enums
import files
import gamedata
from . import enums
from . import files
from . import gamedata
import pygame
from OpenGL.GL import *
from py3dutil import vect
import fonts
from . import fonts
import collections
class Vertex(object):

View file

@ -1,5 +1,5 @@
from py3dutil import vect, quat
import gametimer
from . import gametimer
import math
floor = math.floor

View file

@ -1,8 +1,8 @@
from OpenGL.GL import *
import shader
import physics
from . import shader
from . import physics
from py3dutil import *
from enums import *
from .enums import *
class pipeline_manager(object):
def __init__(self):

View file

@ -1,9 +1,9 @@
import sys
if sys.platform == 'win32':
from platform_win32 import *
from .platform_win32 import *
elif sys.platform == 'darwin':
from platform_darwin import *
from .platform_darwin import *
elif sys.platform in ('posix', 'linux'):
from platform_posix import *
from .platform_posix import *
else:
raise NotImplementedError("Not ported to this platform")

View file

@ -1,11 +1,11 @@
import pygame
import files
import video
import shader
import models
import roc_main
import roc_engine
import config
from . import files
from . import video
from . import shader
from . import models
from . import roc_main
from . import roc_engine
from . import config
base_engine = roc_engine.base_engine
def init2d():

View file

@ -1,5 +1,5 @@
import models
import pipeline
from . import models
from . import pipeline
import pygame
from OpenGL.GL import *
from py3dutil import vect, quat

View file

@ -1,12 +1,12 @@
import pygame
from pygame.locals import *
import gamedata
import gametimer
import video
import shader
import inputs
import models
import config
from . import gamedata
from . import gametimer
from . import video
from . import shader
from . import inputs
from . import models
from . import config
from OpenGL.GL import *

View file

@ -7,7 +7,7 @@ except ImportError:
pass
from OpenGL.arrays import GLintArray, GLcharArray, GLsizeiArray, GLcharARBArray
import sys
import gamedata
from . import gamedata
class shader_manager(object):
@ -84,7 +84,7 @@ class shader_manager(object):
return
self.initialized = True
import files
from . import files
#print glGetString(GL_EXTENSIONS)
if True:
self.use_gl2_shaders()

369
roc/ui.py
View file

@ -1,10 +1,18 @@
import enums
from enums import ui_frametype, ui_postype, ui_filltype
from . import enums
from .enums import ui_frametype, ui_postype, ui_filltype
from pygame.locals import *
import models
import video
from . import models
from . import video
from OpenGL.GL import *
import inputs
from . import inputs
from . import depgraph
from . import gamedata
import itertools
class UITheme(object):
def __init__(self):
self.font = "micross20"
class UIFrame(object):
def __init__(self, content, contentdata):
@ -23,7 +31,10 @@ class UIFrame(object):
self.draggable = False
self.padding = (0, 0)
self.color = None
self.stretchiness = None
if content == ui_frametype.grid:
self.set_stretch_equal()
else:
self.stretchiness = None
def constrain_size(self, x, y):
@ -58,18 +69,19 @@ class UIFrame(object):
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))
# not sure why I originally disabled this but it seems to work ok for now?
#if 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:
@ -98,6 +110,39 @@ class UIFrame(object):
return (0, 0)
def set_stretch_cell(self, col, row):
if self.content != ui_frametype.grid:
raise TypeError("Stretch ratios only apply to grid type UIFrames")
stretchiness_col = [0] * len(self.data)
stretchiness_row = [0] * len(self.data[0])
stretchiness_col[col] = 1
stretchiness_row[row] = 1
self.set_stretch_ratios(stretchiness_col, stretchiness_row)
def set_stretch_equal(self):
if self.content != ui_frametype.grid:
raise TypeError("Stretch ratios only apply to grid type UIFrames")
stretchiness_col = [1] * len(self.data)
stretchiness_row = [1] * len(self.data[0])
self.set_stretch_ratios(stretchiness_col, stretchiness_row)
def set_stretch_ratios(self, stretchiness_col, stretchiness_row):
if self.content != ui_frametype.grid:
raise TypeError("Stretch ratios only apply to grid type UIFrames")
if len(self.data) != len(stretchiness_col):
raise ValueError("Grid has %d columns, but %d stretch ratios were provided" % (len(self.data), len(stretchiness_col)))
if len(self.data[0]) != len(stretchiness_row):
raise ValueError("Grid has %d rows, but %d stretch ratios were provided" % (len(self.data[0]), len(stretchiness_row)))
stretchiness_col = [float(x) / float(sum(stretchiness_col)) for x in stretchiness_col]
stretchiness_row = [float(y) / float(sum(stretchiness_row)) for y in stretchiness_row]
self.stretchiness = (tuple(stretchiness_col), tuple(stretchiness_row))
def autopos(self):
if self.postype == ui_postype.center:
ppos = self.get_parent_pos()
@ -123,17 +168,17 @@ class UIFrame(object):
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")
#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?"""
@ -192,12 +237,10 @@ class UIFrame(object):
y = 0
if xlo > 0:
xs = self.stretchiness[0][ic]
xst = sum(self.stretchiness[0])
x = int(float(xlo) * float(xs) / float(xst))
x = int(float(xlo) * xs)
if ylo > 0:
ys = self.stretchiness[1][ir]
yst = sum(self.stretchiness[1])
y = int(float(ylo) * float(ys) / float(yst))
y = int(float(ylo) * ys)
self.gridsize[0][ic] += x
self.gridsize[1][ir] += y
@ -278,7 +321,10 @@ class UIFrame(object):
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)
if type(self.func) == str:
mgr.get_callback(self.func)(ev)
else:
self.func(ev)
return True
elif ev.type == KEYUP:
@ -397,76 +443,54 @@ class UIFrame(object):
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
#THIS IS OLD EXAMPLE CODE
#
#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
#
#END OLD EXAMPLE CODE
#
class UIManager(object):
def __init__(self):
self.frames = []
self.framenames = {}
self.frame_library = {}
self.focus = None
self.last_mousedown = None
self.mousemove_hook = None
self.debug = 0
self.theme = UITheme()
self.callback_config_list = []
self.callback_configs = {}
def set_theme(self, theme):
self.theme = theme
def set_focus(self, frame):
self.focus = frame
@ -476,9 +500,9 @@ class UIManager(object):
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((frame.pos))
#for child in frame:
# print(("%s-%s" % (child.pos, child.size)))
"""
print "Ok"
print frame.data[1][1].data[1].gridsize
@ -522,5 +546,152 @@ class UIManager(object):
self.drag_hook = None
self.mousedown = None
mgr = UIManager()
def make_box(self, 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.set_stretch_ratios((0, 1, 0), (0, 1, 0))
uf.set_stretch_cell(1,1)
return uf
def make_button(self, text, clickfunc):
text = models.TextModel(self.theme.font, text)
textframe = UIFrame(ui_frametype.model, text)
textframe.postype = ui_postype.center
btnframe = self.make_box("ui_button", textframe, (0.3, 0.3, 1.0, 1.0))
btnframe.func = clickfunc
return btnframe
def load_button(self, data):
name = data["id"]
btn = self.make_button(data["label"], data["callback"])
btn.padding = (data.padding["x"], data.padding["y"])
self.frame_library[name] = btn
def load_frame(self, data):
name = data["id"]
framecolor = (data.color['r'], data.color['g'], data.color['b'], data.color['a'])
frame = self.make_box(name, self.frame_library[data.content['id']], framecolor)
frame.postype = enums.index(ui_postype, data['postype'])
frame.filltype = enums.index(ui_filltype, data['filltype'])
self.frame_library[name] = frame
def load_wrapper(self, data):
name = data["id"]
frame = UIFrame(ui_frametype.composite, [self.frame_library[data.content['id']]])
frame.postype = enums.index(ui_postype, data['postype'])
frame.filltype = enums.index(ui_filltype, data['filltype'])
self.frame_library[name] = frame
def load_grid(self, data):
name = data["id"]
rowcols = []
for r in data.row:
rnum = r['number']
rdata = []
for c in r.col:
cnum = c['number']
rdata.append((cnum, self.frame_library[c.content['id']]))
rdata = zip(*sorted(rdata))[1]
rowcols.append((rnum, rdata))
rowcols = zip(*sorted(rowcols))[1]
frame = UIFrame(ui_frametype.grid, rowcols)
frame.postype = enums.index(ui_postype, data['postype'])
frame.filltype = enums.index(ui_filltype, data['filltype'])
self.frame_library[name] = frame
def load_uidata(self):
uidata = gamedata.get('ui')
framelibdata = {}
# start by preloading the names
for data in itertools.chain(uidata.button, uidata.grid, uidata.frame, uidata.wrapper):
framelibdata[data['id']] = data
dg = depgraph.DepGraph()
for data in uidata.button:
framelibdata[data['id']] = (self.load_button, data)
dg.add(data['id'], [])
for data in uidata.wrapper:
framelibdata[data['id']] = (self.load_wrapper, data)
dg.add(data['id'], [data.content['id']])
for data in uidata.frame:
framelibdata[data['id']] = (self.load_frame, data)
dg.add(data['id'], [data.content['id']])
for data in uidata.grid:
framelibdata[data['id']] = (self.load_grid, data)
gcells = []
for r in data.row:
for c in r.col:
gcells.append(c.content['id'])
dg.add(data['id'], gcells)
dg.resolve()
for dn in dg.bottomup_iter():
df, data = framelibdata[dn]
df(data)
def open_ui(self, name, callback_map, obj=None):
self.callback_config_list.append(name)
self.callback_configs[name] = (callback_map, obj)
frame = self.frame_library[name]
self.add(frame, name)
def close_ui(self, name):
i = self.callback_config_list.index(name)
del self.callback_config_list[i]
del self.callback_configs[name]
self.remove(name)
def get_callback(self, func):
for config in self.callback_config_list:
cc = self.callback_configs[config][0]
if func in cc:
return cc[func]
raise KeyError("Callback function %s not defined" % (func,))
def init():
global mgr
mgr = UIManager()
mgr.load_uidata()
mgr = None

View file

@ -5,9 +5,9 @@ from OpenGL.arrays import GLcharArray
import pygame
from pygame.locals import *
import sys
import shader
import config
import platform
from . import shader
from . import config
from . import platform
height=None
width=None