mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
Put world parsing into World constructor.
This commit is contained in:
parent
db61f5cb59
commit
dc6d0c6c67
|
@ -57,173 +57,12 @@ def get_best_texture(info, optional=False, loader=load_texture):
|
||||||
return cheap, skip, texture
|
return cheap, skip, texture
|
||||||
|
|
||||||
|
|
||||||
def load_world(file):
|
def load_world(file, callback=lambda message, completion: None):
|
||||||
with open(os.path.join(os.path.dirname(__file__), file)) as f:
|
return World(file, callback)
|
||||||
root = json.load(f, object_pairs_hook=OrderedDict)
|
|
||||||
|
|
||||||
world = World()
|
|
||||||
au = root.get('au', 2000)
|
|
||||||
e = lambda x: eval(str(x), {'__builtins__': None}, {'AU': au, 'TEXTURE': texture.max_texture})
|
|
||||||
tick = root.get('tick', 4320) # How many second is a tick?
|
|
||||||
length = root.get('length', 4320) # Satellite distance is in km, divide by this gets in world units
|
|
||||||
world.tick_length = tick
|
|
||||||
|
|
||||||
if 'start' in root:
|
|
||||||
info = root['start']
|
|
||||||
x = e(info.get('x', 0))
|
|
||||||
y = e(info.get('y', 0))
|
|
||||||
z = e(info.get('z', 0))
|
|
||||||
pitch = e(info.get('pitch', 0))
|
|
||||||
yaw = e(info.get('yaw', 0))
|
|
||||||
roll = e(info.get('roll', 0))
|
|
||||||
world.start = (x, y, z)
|
|
||||||
world.direction = (pitch, yaw, roll)
|
|
||||||
|
|
||||||
def body(name, info, parent=None):
|
|
||||||
lighting = info.get('lighting', True)
|
|
||||||
x = e(info.get('x', 0))
|
|
||||||
y = e(info.get('y', 0))
|
|
||||||
z = e(info.get('z', 0))
|
|
||||||
pitch = e(info.get('pitch', 0))
|
|
||||||
yaw = e(info.get('yaw', 0))
|
|
||||||
roll = e(info.get('roll', 0))
|
|
||||||
rotation = e(info.get('rotation', 86400))
|
|
||||||
radius = e(info.get('radius', length)) / length
|
|
||||||
background = info.get('background', False)
|
|
||||||
orbit_distance = e(info.get('orbit_distance', au))
|
|
||||||
division = info.get('division', max(min(int(radius / 8), 60), 10))
|
|
||||||
|
|
||||||
if 'texture' in info:
|
|
||||||
cheap, skip, texture = get_best_texture(info['texture'], optional=info.get('optional', False))
|
|
||||||
if skip:
|
|
||||||
return
|
|
||||||
if cheap:
|
|
||||||
object_id = compile(colourball, radius, division, division, texture)
|
|
||||||
else:
|
|
||||||
if 'normal' in info:
|
|
||||||
object_id = compile(normal_sphere, radius, division, texture, info['normal'], lighting=lighting)
|
|
||||||
else:
|
|
||||||
object_id = compile(sphere, radius, division, division, texture, lighting=lighting)
|
|
||||||
elif 'model' in info:
|
|
||||||
scale = info.get('scale', 1)
|
|
||||||
object_id = model_list(load_model(info['model']), info.get('sx', scale), info.get('sy', scale),
|
|
||||||
info.get('sz', scale), (0, 0, 0))
|
|
||||||
else:
|
|
||||||
print 'Nothing to load for %s.' % name
|
|
||||||
return
|
|
||||||
|
|
||||||
params = {'world': world, 'orbit_distance': orbit_distance}
|
|
||||||
if parent is None:
|
|
||||||
type = Body
|
|
||||||
else:
|
|
||||||
x, y, z = parent.location
|
|
||||||
distance = e(info.get('distance', 100)) # Semi-major axis when actually displayed in virtual space
|
|
||||||
sma = e(info.get('sma', distance)) # Semi-major axis used to calculate orbital speed
|
|
||||||
if hasattr(parent, 'mass') and parent.mass is not None:
|
|
||||||
period = 2 * pi * sqrt((sma * 1000) ** 3 / (G * parent.mass))
|
|
||||||
speed = 360 / (period + .0)
|
|
||||||
if not rotation: # Rotation = 0 assumes tidal lock
|
|
||||||
rotation = period
|
|
||||||
else:
|
|
||||||
speed = info.get('orbit_speed', 1)
|
|
||||||
type = Satellite
|
|
||||||
params.update(parent=parent, orbit_speed=speed,
|
|
||||||
distance=distance / length, eccentricity=info.get('eccentricity', 0),
|
|
||||||
inclination=info.get('inclination', 0), longitude=info.get('longitude', 0),
|
|
||||||
argument=info.get('argument', 0))
|
|
||||||
|
|
||||||
if 'mass' in info:
|
|
||||||
params['mass'] = info['mass']
|
|
||||||
|
|
||||||
atmosphere_id = 0
|
|
||||||
cloudmap_id = 0
|
|
||||||
corona_id = 0
|
|
||||||
if 'atmosphere' in info:
|
|
||||||
atmosphere_data = info['atmosphere']
|
|
||||||
atm_size = e(atmosphere_data.get('diffuse_size', None))
|
|
||||||
atm_texture = atmosphere_data.get('diffuse_texture', None)
|
|
||||||
cloud_texture = atmosphere_data.get('cloud_texture', None)
|
|
||||||
corona_texture = atmosphere_data.get('corona_texture', None)
|
|
||||||
if cloud_texture is not None:
|
|
||||||
cheap, _, cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
|
|
||||||
if not cheap:
|
|
||||||
cloudmap_id = compile(sphere, radius + 2, division, division, cloud_texture,
|
|
||||||
lighting=False)
|
|
||||||
if corona_texture is not None:
|
|
||||||
cheap, _, corona = get_best_texture(corona_texture)
|
|
||||||
if not cheap:
|
|
||||||
corona_size = atmosphere_data.get('corona_size', radius / 2)
|
|
||||||
corona_division = atmosphere_data.get('corona_division', 100)
|
|
||||||
corona_ratio = atmosphere_data.get('corona_ratio', 0.5)
|
|
||||||
corona_id = compile(flare, radius, radius + corona_size, corona_division,
|
|
||||||
corona_ratio, corona)
|
|
||||||
|
|
||||||
if atm_texture is not None:
|
|
||||||
cheap, _, atm_texture = get_best_texture(atm_texture)
|
|
||||||
if not cheap:
|
|
||||||
atmosphere_id = compile(disk, radius, radius + atm_size, 30, atm_texture)
|
|
||||||
|
|
||||||
theta = 360 / (rotation + .0) if rotation else 0
|
|
||||||
object = type(object_id, (x, y, z), (pitch, yaw, roll), rotation_angle=theta,
|
|
||||||
atmosphere=atmosphere_id, cloudmap=cloudmap_id, background=background,
|
|
||||||
corona=corona_id, **params)
|
|
||||||
world.tracker.append(object)
|
|
||||||
|
|
||||||
if 'ring' in info:
|
|
||||||
ring_data = info['ring']
|
|
||||||
texture = ring_data.get('texture', None)
|
|
||||||
distance = e(ring_data.get('distance', radius * 1.2))
|
|
||||||
size = e(ring_data.get('size', radius / 2))
|
|
||||||
pitch = e(ring_data.get('pitch', pitch))
|
|
||||||
yaw = e(ring_data.get('yaw', yaw))
|
|
||||||
roll = e(ring_data.get('roll', roll))
|
|
||||||
|
|
||||||
cheap, _, texture = get_best_texture(texture)
|
|
||||||
if not cheap:
|
|
||||||
world.tracker.append(
|
|
||||||
type(compile(disk, distance, distance + size, 30, texture), (x, y, z),
|
|
||||||
(pitch, yaw, roll), **params))
|
|
||||||
|
|
||||||
for satellite, info in info.get('satellites', {}).iteritems():
|
|
||||||
print 'Loading %s, satellite of %s.' % (satellite, name)
|
|
||||||
body(satellite, info, object)
|
|
||||||
|
|
||||||
for planet, info in root['bodies'].iteritems():
|
|
||||||
print 'Loading %s.' % planet
|
|
||||||
body(planet, info)
|
|
||||||
|
|
||||||
for name, info in root['belts'].iteritems():
|
|
||||||
print 'Loading %s.' % name
|
|
||||||
x = e(info.get('x', 0))
|
|
||||||
y = e(info.get('y', 0))
|
|
||||||
z = e(info.get('z', 0))
|
|
||||||
radius = e(info.get('radius', 0))
|
|
||||||
cross = e(info.get('cross', 0))
|
|
||||||
count = int(e(info.get('count', 0)))
|
|
||||||
scale = info.get('scale', 1)
|
|
||||||
longitude = info.get('longitude', 0)
|
|
||||||
inclination = info.get('inclination', 0)
|
|
||||||
argument = info.get('argument', 0)
|
|
||||||
rotation = info.get('period', 31536000)
|
|
||||||
theta = 360 / (rotation + .0) if rotation else 0
|
|
||||||
|
|
||||||
models = info['model']
|
|
||||||
if not isinstance(models, list):
|
|
||||||
models = [models]
|
|
||||||
objects = []
|
|
||||||
for model in models:
|
|
||||||
objects.append(model_list(load_model(model), info.get('sx', scale), info.get('sy', scale),
|
|
||||||
info.get('sz', scale), (0, 0, 0)))
|
|
||||||
|
|
||||||
world.tracker.append(Belt(compile(belt, radius, cross, objects, count),
|
|
||||||
(x, y, z), (inclination, longitude, argument),
|
|
||||||
rotation_angle=theta, world=world))
|
|
||||||
|
|
||||||
return world
|
|
||||||
|
|
||||||
|
|
||||||
class World(object):
|
class World(object):
|
||||||
def __init__(self):
|
def __init__(self, file, callback):
|
||||||
self.tracker = []
|
self.tracker = []
|
||||||
self.start = (0, 0, 0)
|
self.start = (0, 0, 0)
|
||||||
self.direction = (0, 0, 0)
|
self.direction = (0, 0, 0)
|
||||||
|
@ -232,3 +71,174 @@ class World(object):
|
||||||
self.z = None
|
self.z = None
|
||||||
self.tick_length = 1
|
self.tick_length = 1
|
||||||
self.tick = 0
|
self.tick = 0
|
||||||
|
|
||||||
|
self.callback = callback
|
||||||
|
self._parse(file)
|
||||||
|
del self.callback # So it can't be used after loading finishes
|
||||||
|
|
||||||
|
def _eval(self, value):
|
||||||
|
return eval(str(value), {'__builtins__': None}, self.context)
|
||||||
|
|
||||||
|
def _parse(self, file):
|
||||||
|
self.callback('Loading configuration file...', 0)
|
||||||
|
with open(os.path.join(os.path.dirname(__file__), file)) as f:
|
||||||
|
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}
|
||||||
|
|
||||||
|
tick = root.get('tick', 4320) # How many second is a tick?
|
||||||
|
self.tick_length = tick
|
||||||
|
|
||||||
|
if 'start' in root:
|
||||||
|
info = root['start']
|
||||||
|
x = self._eval(info.get('x', 0))
|
||||||
|
y = self._eval(info.get('y', 0))
|
||||||
|
z = self._eval(info.get('z', 0))
|
||||||
|
pitch = self._eval(info.get('pitch', 0))
|
||||||
|
yaw = self._eval(info.get('yaw', 0))
|
||||||
|
roll = self._eval(info.get('roll', 0))
|
||||||
|
self.start = (x, y, z)
|
||||||
|
self.direction = (pitch, yaw, roll)
|
||||||
|
|
||||||
|
for planet, info in root['bodies'].iteritems():
|
||||||
|
print 'Loading %s.' % planet
|
||||||
|
self._body(planet, info)
|
||||||
|
|
||||||
|
for name, info in root['belts'].iteritems():
|
||||||
|
print 'Loading %s.' % name
|
||||||
|
|
||||||
|
def _belt(self, name, info):
|
||||||
|
x = self._eval(info.get('x', 0))
|
||||||
|
y = self._eval(info.get('y', 0))
|
||||||
|
z = self._eval(info.get('z', 0))
|
||||||
|
radius = self._eval(info.get('radius', 0))
|
||||||
|
cross = self._eval(info.get('cross', 0))
|
||||||
|
count = int(self._eval(info.get('count', 0)))
|
||||||
|
scale = info.get('scale', 1)
|
||||||
|
longitude = info.get('longitude', 0)
|
||||||
|
inclination = info.get('inclination', 0)
|
||||||
|
argument = info.get('argument', 0)
|
||||||
|
rotation = info.get('period', 31536000)
|
||||||
|
theta = 360 / (rotation + .0) if rotation else 0
|
||||||
|
|
||||||
|
models = info['model']
|
||||||
|
if not isinstance(models, list):
|
||||||
|
models = [models]
|
||||||
|
objects = []
|
||||||
|
for model in models:
|
||||||
|
objects.append(model_list(load_model(model), info.get('sx', scale), info.get('sy', scale),
|
||||||
|
info.get('sz', scale), (0, 0, 0)))
|
||||||
|
|
||||||
|
self.tracker.append(Belt(compile(belt, radius, cross, objects, count),
|
||||||
|
(x, y, z), (inclination, longitude, argument),
|
||||||
|
rotation_angle=theta, world=self))
|
||||||
|
|
||||||
|
def _body(self, name, info, parent=None):
|
||||||
|
lighting = info.get('lighting', True)
|
||||||
|
x = self._eval(info.get('x', 0))
|
||||||
|
y = self._eval(info.get('y', 0))
|
||||||
|
z = self._eval(info.get('z', 0))
|
||||||
|
pitch = self._eval(info.get('pitch', 0))
|
||||||
|
yaw = self._eval(info.get('yaw', 0))
|
||||||
|
roll = self._eval(info.get('roll', 0))
|
||||||
|
rotation = self._eval(info.get('rotation', 86400))
|
||||||
|
radius = self._eval(info.get('radius', self.length)) / self.length
|
||||||
|
background = info.get('background', False)
|
||||||
|
orbit_distance = self._eval(info.get('orbit_distance', self.au))
|
||||||
|
division = info.get('division', max(min(int(radius / 8), 60), 10))
|
||||||
|
|
||||||
|
if 'texture' in info:
|
||||||
|
cheap, skip, texture = get_best_texture(info['texture'], optional=info.get('optional', False))
|
||||||
|
if skip:
|
||||||
|
return
|
||||||
|
if cheap:
|
||||||
|
object_id = compile(colourball, radius, division, division, texture)
|
||||||
|
else:
|
||||||
|
if 'normal' in info:
|
||||||
|
object_id = compile(normal_sphere, radius, division, texture, info['normal'], lighting=lighting)
|
||||||
|
else:
|
||||||
|
object_id = compile(sphere, radius, division, division, texture, lighting=lighting)
|
||||||
|
elif 'model' in info:
|
||||||
|
scale = info.get('scale', 1)
|
||||||
|
object_id = model_list(load_model(info['model']), info.get('sx', scale), info.get('sy', scale),
|
||||||
|
info.get('sz', scale), (0, 0, 0))
|
||||||
|
else:
|
||||||
|
print 'Nothing to load for %s.' % name
|
||||||
|
return
|
||||||
|
|
||||||
|
params = {'world': self, 'orbit_distance': orbit_distance}
|
||||||
|
if parent is None:
|
||||||
|
type = Body
|
||||||
|
else:
|
||||||
|
x, y, z = parent.location
|
||||||
|
distance = self._eval(info.get('distance', 100)) # Semi-major axis when actually displayed in virtual space
|
||||||
|
sma = self._eval(info.get('sma', distance)) # Semi-major axis used to calculate orbital speed
|
||||||
|
if hasattr(parent, 'mass') and parent.mass is not None:
|
||||||
|
period = 2 * pi * sqrt((sma * 1000) ** 3 / (G * parent.mass))
|
||||||
|
speed = 360 / (period + .0)
|
||||||
|
if not rotation: # Rotation = 0 assumes tidal lock
|
||||||
|
rotation = period
|
||||||
|
else:
|
||||||
|
speed = info.get('orbit_speed', 1)
|
||||||
|
type = Satellite
|
||||||
|
params.update(parent=parent, orbit_speed=speed,
|
||||||
|
distance=distance / self.length, eccentricity=info.get('eccentricity', 0),
|
||||||
|
inclination=info.get('inclination', 0), longitude=info.get('longitude', 0),
|
||||||
|
argument=info.get('argument', 0))
|
||||||
|
|
||||||
|
if 'mass' in info:
|
||||||
|
params['mass'] = info['mass']
|
||||||
|
|
||||||
|
atmosphere_id = 0
|
||||||
|
cloudmap_id = 0
|
||||||
|
corona_id = 0
|
||||||
|
if 'atmosphere' in info:
|
||||||
|
atmosphere_data = info['atmosphere']
|
||||||
|
atm_size = self._eval(atmosphere_data.get('diffuse_size', None))
|
||||||
|
atm_texture = atmosphere_data.get('diffuse_texture', None)
|
||||||
|
cloud_texture = atmosphere_data.get('cloud_texture', None)
|
||||||
|
corona_texture = atmosphere_data.get('corona_texture', None)
|
||||||
|
if cloud_texture is not None:
|
||||||
|
cheap, _, cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
|
||||||
|
if not cheap:
|
||||||
|
cloudmap_id = compile(sphere, radius + 2, division, division, cloud_texture,
|
||||||
|
lighting=False)
|
||||||
|
if corona_texture is not None:
|
||||||
|
cheap, _, corona = get_best_texture(corona_texture)
|
||||||
|
if not cheap:
|
||||||
|
corona_size = atmosphere_data.get('corona_size', radius / 2)
|
||||||
|
corona_division = atmosphere_data.get('corona_division', 100)
|
||||||
|
corona_ratio = atmosphere_data.get('corona_ratio', 0.5)
|
||||||
|
corona_id = compile(flare, radius, radius + corona_size, corona_division,
|
||||||
|
corona_ratio, corona)
|
||||||
|
|
||||||
|
if atm_texture is not None:
|
||||||
|
cheap, _, atm_texture = get_best_texture(atm_texture)
|
||||||
|
if not cheap:
|
||||||
|
atmosphere_id = compile(disk, radius, radius + atm_size, 30, atm_texture)
|
||||||
|
|
||||||
|
theta = 360 / (rotation + .0) if rotation else 0
|
||||||
|
object = type(object_id, (x, y, z), (pitch, yaw, roll), rotation_angle=theta,
|
||||||
|
atmosphere=atmosphere_id, cloudmap=cloudmap_id, background=background,
|
||||||
|
corona=corona_id, **params)
|
||||||
|
self.tracker.append(object)
|
||||||
|
|
||||||
|
if 'ring' in info:
|
||||||
|
ring_data = info['ring']
|
||||||
|
texture = ring_data.get('texture', None)
|
||||||
|
distance = self._eval(ring_data.get('distance', radius * 1.2))
|
||||||
|
size = self._eval(ring_data.get('size', radius / 2))
|
||||||
|
pitch = self._eval(ring_data.get('pitch', pitch))
|
||||||
|
yaw = self._eval(ring_data.get('yaw', yaw))
|
||||||
|
roll = self._eval(ring_data.get('roll', roll))
|
||||||
|
|
||||||
|
cheap, _, texture = get_best_texture(texture)
|
||||||
|
if not cheap:
|
||||||
|
self.tracker.append(
|
||||||
|
type(compile(disk, distance, distance + size, 30, texture), (x, y, z),
|
||||||
|
(pitch, yaw, roll), **params))
|
||||||
|
|
||||||
|
for satellite, info in info.get('satellites', {}).iteritems():
|
||||||
|
print 'Loading %s, satellite of %s.' % (satellite, name)
|
||||||
|
self._body(satellite, info, object)
|
Loading…
Reference in a new issue