mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 05:01:57 -04:00
Use dedicated loader window to perform loading.
This paves the way to use OpenGL core profile in the future while still using legacy to draw the simple loader.
This commit is contained in:
parent
88bf6d1dff
commit
aa225c70fa
|
@ -1,9 +1,9 @@
|
|||
from math import *
|
||||
from random import random, gauss, choice
|
||||
|
||||
from pyglet.gl import *
|
||||
# noinspection PyUnresolvedReferences
|
||||
from six.moves import range
|
||||
from pyglet.gl import *
|
||||
|
||||
TWOPI = pi * 2
|
||||
|
||||
|
@ -11,6 +11,18 @@ __all__ = ['compile', 'ortho', 'frustrum', 'crosshair', 'circle', 'disk', 'spher
|
|||
'flare', 'glSection', 'glMatrix', 'glRestore', 'progress_bar']
|
||||
|
||||
|
||||
class glContext(object):
|
||||
def __init__(self, context):
|
||||
self.new_context = context
|
||||
|
||||
def __enter__(self):
|
||||
self.old_context = get_current_context()
|
||||
self.new_context.set_current()
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.old_context.set_current()
|
||||
|
||||
|
||||
class glSection(object):
|
||||
def __init__(self, type):
|
||||
self.type = type
|
||||
|
|
76
punyverse/loader.py
Normal file
76
punyverse/loader.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
import time
|
||||
|
||||
import pyglet
|
||||
from pyglet.gl import *
|
||||
from six.moves import zip_longest
|
||||
|
||||
from punyverse.glgeom import glContext, progress_bar
|
||||
from punyverse.world import World
|
||||
|
||||
|
||||
class LoaderWindow(pyglet.window.Window):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LoaderWindow, self).__init__(*args, **kwargs)
|
||||
|
||||
self.loading_phase = pyglet.text.Label(
|
||||
font_name='Consolas', font_size=20, x=10, y=self.height - 50,
|
||||
color=(255, 255, 255, 255), width=self.width - 20, align='center',
|
||||
multiline=True, text='Punyverse is starting...'
|
||||
)
|
||||
self.loading_label = pyglet.text.Label(
|
||||
font_name='Consolas', font_size=16, x=10, y=self.height - 120,
|
||||
color=(255, 255, 255, 255), width=self.width - 20, align='center',
|
||||
multiline=True
|
||||
)
|
||||
self.info_label = pyglet.text.Label(
|
||||
font_name='Consolas', font_size=13, x=10, y=self.height - 220,
|
||||
color=(255, 255, 255, 255), width=self.width - 20,
|
||||
multiline=True
|
||||
)
|
||||
self.progress = 0
|
||||
|
||||
self._main_context = None
|
||||
|
||||
def set_main_context(self, context):
|
||||
self._main_context = context
|
||||
|
||||
info = [' %-22s %s' % (key + ':', value)
|
||||
for key, value in context.config.get_gl_attributes()]
|
||||
info = ['%-30s %-30s' % group for group in
|
||||
zip_longest(info[::2], info[1::2], fillvalue='')]
|
||||
|
||||
with glContext(context):
|
||||
self.info_label.text = '\n'.join([
|
||||
'Graphics Vendor: ' + gl_info.get_vendor(),
|
||||
'Graphics Version: ' + gl_info.get_version(),
|
||||
'Graphics Renderer: ' + gl_info.get_renderer(),
|
||||
]) + '\n\n' + 'OpenGL configuration:\n' + '\n'.join(info)
|
||||
|
||||
def _load_callback(self, phase, message, progress):
|
||||
print(message)
|
||||
with glContext(self.context):
|
||||
self.loading_phase.text = phase
|
||||
self.loading_label.text = message
|
||||
self.progress = progress
|
||||
|
||||
self.on_draw()
|
||||
self.flip()
|
||||
self.dispatch_events()
|
||||
|
||||
def load(self):
|
||||
start = time.clock()
|
||||
with glContext(self._main_context):
|
||||
world = World('world.json', self._load_callback)
|
||||
print('Loaded in %s seconds.' % (time.clock() - start))
|
||||
return world
|
||||
|
||||
def on_draw(self):
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
glLoadIdentity()
|
||||
self.loading_phase.draw()
|
||||
self.loading_label.draw()
|
||||
progress_bar(10, self.height - 140, self.width - 20, 50, self.progress)
|
||||
self.info_label.draw()
|
||||
|
||||
def main_is_initializing(self):
|
||||
self._load_callback('Loading main window...', '', 0)
|
|
@ -2,7 +2,8 @@ import argparse
|
|||
|
||||
import pyglet
|
||||
|
||||
from punyverse import game
|
||||
from punyverse.loader import LoaderWindow
|
||||
from punyverse.ui import Punyverse
|
||||
|
||||
INITIAL_WIN_HEIGHT = 540
|
||||
INITIAL_WIN_WIDTH = 700
|
||||
|
@ -24,10 +25,12 @@ def main():
|
|||
args = parser.parse_args()
|
||||
|
||||
pyglet.options['shadow_window'] = False
|
||||
loader = LoaderWindow(width=INITIAL_WIN_WIDTH, height=INITIAL_WIN_HEIGHT)
|
||||
|
||||
template = pyglet.gl.Config(depth_size=args.depth, double_buffer=True,
|
||||
sample_buffers=args.multisample > 1,
|
||||
samples=args.multisample)
|
||||
samples=args.multisample,
|
||||
major_version=3)
|
||||
|
||||
platform = pyglet.window.get_platform()
|
||||
display = platform.get_default_display()
|
||||
|
@ -42,9 +45,17 @@ def main():
|
|||
for key in config._attribute_names:
|
||||
print(' %-22s %s' % (key + ':', getattr(config, key)))
|
||||
|
||||
game.Applet(width=INITIAL_WIN_WIDTH, height=INITIAL_WIN_HEIGHT,
|
||||
caption=WIN_TITLE, resizable=True, vsync=args.vsync,
|
||||
config=config)
|
||||
punyverse = Punyverse(width=INITIAL_WIN_WIDTH, height=INITIAL_WIN_HEIGHT,
|
||||
caption=WIN_TITLE, resizable=True, vsync=args.vsync,
|
||||
config=config, visible=False)
|
||||
|
||||
loader.set_main_context(punyverse.context)
|
||||
world = loader.load()
|
||||
punyverse.context.set_current()
|
||||
punyverse.initialize(world)
|
||||
loader.close()
|
||||
punyverse.set_visible(True)
|
||||
|
||||
pyglet.app.run()
|
||||
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ except ImportError:
|
|||
import warnings
|
||||
warnings.warn('Compile _glgeom.c, or double the start up time.')
|
||||
|
||||
|
||||
def bgr_to_rgb(source, width, height, alpha=False):
|
||||
length = len(source)
|
||||
depth = length // (width * height)
|
||||
|
@ -47,25 +48,9 @@ __all__ = ['load_texture', 'load_clouds', 'load_image', 'get_best_texture']
|
|||
id = 0
|
||||
cache = {}
|
||||
|
||||
max_texture = None
|
||||
power_of_two = None
|
||||
bgra = False
|
||||
|
||||
|
||||
def init():
|
||||
global max_texture, power_of_two, bgra
|
||||
|
||||
if max_texture is None:
|
||||
buf = c_int()
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, byref(buf))
|
||||
max_texture = buf.value
|
||||
bgra = gl_info.have_extension('GL_EXT_bgra')
|
||||
|
||||
if power_of_two is None:
|
||||
power_of_two = gl_info.have_version(2) or gl_info.have_extension('GL_ARB_texture_non_power_of_two')
|
||||
|
||||
|
||||
is_power2 = lambda num: num != 0 and ((num & (num - 1)) == 0)
|
||||
def is_power2(num):
|
||||
return num != 0 and ((num & (num - 1)) == 0)
|
||||
|
||||
|
||||
def image_info(data):
|
||||
|
@ -126,12 +111,19 @@ def image_info(data):
|
|||
return content_type, width, height
|
||||
|
||||
|
||||
def max_texture_size():
|
||||
buf = c_int()
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, byref(buf))
|
||||
return buf.value
|
||||
|
||||
|
||||
def check_size(width, height):
|
||||
init()
|
||||
max_texture = max_texture_size()
|
||||
|
||||
if width > max_texture or height > max_texture:
|
||||
print('too large')
|
||||
raise ValueError('Texture too large')
|
||||
elif not power_of_two:
|
||||
elif not gl_info.have_version(2) and not gl_info.have_extension('GL_ARB_texture_non_power_of_two'):
|
||||
if not is_power2(width) or not is_power2(height):
|
||||
print('not power of two')
|
||||
raise ValueError('Texture not power of two')
|
||||
|
@ -165,7 +157,7 @@ def load_image(file, path):
|
|||
|
||||
# Flip from BGR to RGB
|
||||
if raw.format in ('BGR', 'BGRA'):
|
||||
if bgra:
|
||||
if gl_info.have_extension('GL_EXT_bgra'):
|
||||
mode = GL_BGRA if 'A' in raw.format else GL_BGR
|
||||
texture = raw.data
|
||||
else:
|
||||
|
|
|
@ -3,29 +3,19 @@ import os
|
|||
import time
|
||||
from math import hypot
|
||||
from operator import attrgetter
|
||||
from time import clock
|
||||
|
||||
import pyglet
|
||||
import six
|
||||
from pyglet.gl import *
|
||||
from pyglet.window import key, mouse
|
||||
|
||||
from punyverse import texture
|
||||
from punyverse.glgeom import *
|
||||
from punyverse.world import World
|
||||
|
||||
try:
|
||||
from punyverse._model import model_list, load_model
|
||||
except ImportError:
|
||||
from punyverse.model import model_list, load_model
|
||||
|
||||
try:
|
||||
from itertools import zip_longest
|
||||
except ImportError:
|
||||
from itertools import izip_longest as zip_longest
|
||||
|
||||
from pyglet.gl import *
|
||||
from pyglet.window import key, mouse
|
||||
|
||||
import pyglet
|
||||
|
||||
MOUSE_SENSITIVITY = 0.3 # Mouse sensitivity, 0..1, none...hyperspeed
|
||||
|
||||
MAX_DELTA = 5
|
||||
|
@ -40,55 +30,11 @@ def entity_distance(x0, y0, z0):
|
|||
return distance
|
||||
|
||||
|
||||
class Applet(pyglet.window.Window):
|
||||
class Punyverse(pyglet.window.Window):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Applet, self).__init__(*args, **kwargs)
|
||||
texture.init()
|
||||
super(Punyverse, self).__init__(*args, **kwargs)
|
||||
|
||||
if hasattr(self.config, '_attribute_names'):
|
||||
info = [' %-22s %s' % (key + ':', value)
|
||||
for key, value in self.config.get_gl_attributes()]
|
||||
info = ['%-30s %-30s' % group for group in
|
||||
zip_longest(info[::2], info[1::2], fillvalue='')]
|
||||
info = 'OpenGL configuration:\n' + '\n'.join(info)
|
||||
else:
|
||||
info = 'Unknown OpenGL configuration'
|
||||
|
||||
info = '\n'.join([
|
||||
'Graphics Vendor: ' + gl_info.get_vendor(),
|
||||
'Graphics Version: ' + gl_info.get_version(),
|
||||
'Graphics Renderer: ' + gl_info.get_renderer(),
|
||||
]) + '\n\n' + info
|
||||
|
||||
self.loaded = False
|
||||
self._loading_phase = pyglet.text.Label(
|
||||
font_name='Consolas', font_size=20, x=10, y=self.height - 50,
|
||||
color=(255, 255, 255, 255), width=self.width - 20, align='center',
|
||||
multiline=True, text='Punyverse is starting...'
|
||||
)
|
||||
self._loading_label = pyglet.text.Label(
|
||||
font_name='Consolas', font_size=16, x=10, y=self.height - 120,
|
||||
color=(255, 255, 255, 255), width=self.width - 20, align='center',
|
||||
multiline=True
|
||||
)
|
||||
self._info_label = pyglet.text.Label(
|
||||
font_name='Consolas', font_size=13, x=10, y=self.height - 220,
|
||||
color=(255, 255, 255, 255), width=self.width - 20,
|
||||
multiline=True, text=info
|
||||
)
|
||||
pyglet.clock.schedule_once(self.load, 0)
|
||||
|
||||
def _load_callback(self, phase, message, progress):
|
||||
print(message)
|
||||
self.draw_loading(phase, message, progress)
|
||||
self.flip()
|
||||
self.dispatch_events()
|
||||
|
||||
def load(self, *args, **kwargs):
|
||||
start = clock()
|
||||
self.fps = 0
|
||||
self.world = World('world.json', self._load_callback)
|
||||
self._load_callback('Initializing game...', '', 0)
|
||||
self.info = True
|
||||
self.debug = False
|
||||
self.orbit = True
|
||||
|
@ -109,6 +55,19 @@ class Applet(pyglet.window.Window):
|
|||
630720000, 1576800000, 3153600000, # 20, 50, 100 years
|
||||
]
|
||||
|
||||
self.key_handler = {}
|
||||
self.mouse_press_handler = {}
|
||||
|
||||
self.label = pyglet.text.Label('', font_name='Consolas', font_size=12, x=10, y=self.height - 20,
|
||||
color=(255,) * 4, multiline=True, width=600)
|
||||
self.exclusive = False
|
||||
self.modifiers = 0
|
||||
|
||||
self.world = None
|
||||
|
||||
def initialize(self, world):
|
||||
self.world = world
|
||||
|
||||
def speed_incrementer(object, increment):
|
||||
def incrementer():
|
||||
object.speed += increment
|
||||
|
@ -163,11 +122,6 @@ class Applet(pyglet.window.Window):
|
|||
mouse.RIGHT: attribute_toggler(self, 'moving'),
|
||||
}
|
||||
|
||||
self.label = pyglet.text.Label('', font_name='Consolas', font_size=12, x=10, y=self.height - 20,
|
||||
color=(255,) * 4, multiline=True, width=600)
|
||||
|
||||
self.exclusive = False
|
||||
|
||||
glClearColor(0, 0, 0, 1)
|
||||
glClearDepth(1.0)
|
||||
|
||||
|
@ -193,8 +147,6 @@ class Applet(pyglet.window.Window):
|
|||
glLightfv(GL_LIGHT1, GL_DIFFUSE, fv4(.5, .5, .5, 1))
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, fv4(1, 1, 1, 1))
|
||||
|
||||
print('Loaded in %s seconds.' % (clock() - start))
|
||||
self.loaded = True
|
||||
pyglet.clock.schedule(self.update)
|
||||
self.on_resize(self.width, self.height) # On resize handler does nothing unless it's loaded
|
||||
|
||||
|
@ -225,13 +177,11 @@ class Applet(pyglet.window.Window):
|
|||
image.save(os.path.expanduser('~/punyverse.png'))
|
||||
|
||||
def set_exclusive_mouse(self, exclusive):
|
||||
super(Applet, self).set_exclusive_mouse(exclusive)
|
||||
super(Punyverse, self).set_exclusive_mouse(exclusive)
|
||||
self.exclusive = exclusive
|
||||
|
||||
def on_mouse_press(self, x, y, button, modifiers):
|
||||
self.modifiers = modifiers
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
if not self.exclusive:
|
||||
self.set_exclusive_mouse(True)
|
||||
|
@ -240,9 +190,6 @@ class Applet(pyglet.window.Window):
|
|||
self.mouse_press_handler[button]()
|
||||
|
||||
def on_mouse_motion(self, x, y, dx, dy):
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
if self.exclusive: # Only handle camera movement if mouse is grabbed
|
||||
self.world.cam.mouse_move(dx * MOUSE_SENSITIVITY, dy * MOUSE_SENSITIVITY)
|
||||
|
||||
|
@ -250,8 +197,7 @@ class Applet(pyglet.window.Window):
|
|||
self.modifiers = modifiers
|
||||
if symbol == key.Q:
|
||||
self.screenshot()
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
if self.exclusive: # Only handle keyboard input if mouse is grabbed
|
||||
if symbol in self.key_handler:
|
||||
self.key_handler[symbol]()
|
||||
|
@ -261,18 +207,12 @@ class Applet(pyglet.window.Window):
|
|||
self.world.cam.roll_right = True
|
||||
|
||||
def on_key_release(self, symbol, modifiers):
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
if symbol == key.A:
|
||||
self.world.cam.roll_left = False
|
||||
elif symbol == key.S:
|
||||
self.world.cam.roll_right = False
|
||||
|
||||
def on_resize(self, width, height):
|
||||
if not self.loaded:
|
||||
return super(Applet, self).on_resize(width, height)
|
||||
|
||||
height = max(height, 1) # Prevent / by 0
|
||||
self.label.y = height - 20
|
||||
glViewport(0, 0, width, height)
|
||||
|
@ -283,9 +223,6 @@ class Applet(pyglet.window.Window):
|
|||
glMatrixMode(GL_MODELVIEW)
|
||||
|
||||
def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
self.world.cam.speed += scroll_y * 50 + scroll_x * 500
|
||||
|
||||
def get_time_per_second(self):
|
||||
|
@ -302,23 +239,7 @@ class Applet(pyglet.window.Window):
|
|||
def update(self, dt):
|
||||
self.world.update(dt, move=self.exclusive and self.moving, tick=self.running)
|
||||
|
||||
def draw_loading(self, phase=None, message=None, progress=None):
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
glLoadIdentity()
|
||||
if phase is not None:
|
||||
self._loading_phase.text = phase
|
||||
if message is not None:
|
||||
self._loading_label.text = message
|
||||
self._loading_phase.draw()
|
||||
self._loading_label.draw()
|
||||
if progress is not None:
|
||||
progress_bar(10, self.height - 140, self.width - 20, 50, progress)
|
||||
self._info_label.draw()
|
||||
|
||||
def on_draw(self):
|
||||
if not self.loaded:
|
||||
return self.draw_loading()
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
glLoadIdentity()
|
||||
|
|
@ -57,7 +57,7 @@ class World(object):
|
|||
root = json.load(f, object_pairs_hook=OrderedDict)
|
||||
self._au = root.get('au', 2000)
|
||||
self._length = root.get('length', 4320)
|
||||
self._context = {'AU': self._au, 'TEXTURE': texture.max_texture, 'KM': 1.0 / self._length}
|
||||
self._context = {'AU': self._au, 'TEXTURE': texture.max_texture_size(), 'KM': 1.0 / self._length}
|
||||
|
||||
self.tick_length = root.get('tick', 4320) # How many second is a tick?
|
||||
|
||||
|
|
Loading…
Reference in a new issue