from .core import *
from . import config
from .errors import *
from . import physics
from time import time
import os
from OpenGL.GL import *
from OpenGL.GLU import *
[docs]class SceneManager:
"""
Class to manage scenes.
Attributes
----------
scenesByIndex : list
List of scenes
scenesByName : dict
Dictionary of scenes, with the scene
names as the keys.
"""
def __init__(self):
"""
Create a scene manager.
"""
self.scenesByIndex = []
self.scenesByName = {}
def AddScene(self, sceneName):
"""
Add a scene to the SceneManager. Pass
in a scene name to create a scene.
Parameters
----------
sceneName : str
Name of the scene
Returns
-------
Scene
Newly created scene
Raises
------
PyUnityException
If there already exists a scene called `sceneName`
"""
if sceneName in self.scenesByName:
raise PyUnityException("SceneManager already contains scene \"" + \
sceneName + "\"")
scene = Scene(sceneName)
self.scenesByIndex.append(scene)
self.scenesByName[sceneName] = scene
return scene
def GetSceneByIndex(self, index):
"""
Get a scene by its index.
Parameters
----------
index : int
Index of the scene
Returns
-------
Scene
Specified scene at index `index`
Raises
------
IndexError
If there is no scene at the specified index
"""
if len(self.scenesByIndex) <= index:
raise IndexError("There is no scene at index " + str(index))
return self.scenesByIndex[index]
def GetSceneByName(self, name):
"""
Get a scene by its name.
Parameters
----------
name : str
Name of the scene
Returns
-------
Scene
Specified scene with name of `name`
Raises
------
KeyError
If there is no scene called `name`
"""
if name not in self.scenesByName:
raise KeyError("There is no scene called " + name)
return self.scenesByName[name]
def RemoveScene(self, scene):
if not isinstance(scene, Scene):
raise PyUnityException("The provided scene is not of type Scene")
if scene not in self.scenesByIndex:
raise PyUnityException("Scene \"" + scene.name + "\" is not part of the SceneManager")
self.scenesByIndex.remove(scene)
self.scenesByName.pop(scene.name)
SceneManager = SceneManager()
"""Manages all scene additions and changes"""
[docs]class Scene:
"""
Class to hold all of the GameObjects, and to run the whole
scene.
Parameters
----------
name : str
Name of the scene
Notes
-----
Create a scene using the SceneManager, and don't create a scene
directly using this class.
"""
def __init__(self, name):
self.name = name
self.mainCamera = GameObject("Main Camera").AddComponent(Camera)
light = GameObject("Light")
light.AddComponent(Light)
light.transform.position = Vector3(10, 5, -5)
self.gameObjects = [self.mainCamera.gameObject, light]
self.rootGameObjects = [self.mainCamera.gameObject, light]
[docs] def Add(self, gameObject):
"""
Add a GameObject to the scene.
Parameters
----------
gameObject : GameObejct
The GameObject to add.
"""
self.gameObjects.append(gameObject)
if gameObject.transform.parent is None:
self.rootGameObjects.append(gameObject)
[docs] def Remove(self, gameObject):
"""
Remove a GameObject from the scene.
Parameters
----------
gameObject : GameObject
GameObject to remove.
Raises
------
PyUnityException
If the specified GameObject is the Main Camera.
"""
if gameObject not in [self.mainCamera]:
flag = False
for go in self.gameObjects:
if go == gameObject:
flag = True
break
if flag: self.gameObjects.remove(gameObject)
else:
raise PyUnityException("Cannot remove the Main Camera from the scene")
[docs] def List(self):
"""
Lists all the GameObjects currently in the scene.
"""
for gameObject in sorted(self.rootGameObjects, key = lambda x: x.name):
gameObject.transform.List()
[docs] def FindGameObjectsByName(self, name):
"""
Finds all GameObjects matching the specified name.
Parameters
----------
name : str
Name of the GameObject
Returns
-------
list
List of the matching GameObjects
"""
return [gameObject for gameObject in self.gameObjects if gameObject.name == name]
[docs] def FindGameObjectsByTagName(self, name):
"""
Finds all GameObjects with the specified tag name.
Parameters
----------
name : str
Name of the tag
Returns
-------
list
List of matching GameObjects
Raises
------
GameObjectException
When there is no tag named `name`
"""
if name in tags:
return [gameObject for gameObject in self.gameObjects if gameObject.tag.tagName == name]
else:
raise GameObjectException("No tag named " + name + "; create a new tag with Tag.AddTag")
[docs] def FindGameObjectsByTagNumber(self, num):
"""
Gets all GameObjects with a tag of tag `num`.
Parameters
----------
num : int
Index of the tag
Returns
-------
list
List of matching GameObjects
Raises
------
GameObjectException
If there is no tag with specified index.
"""
if len(tags) > num:
return [gameObject for gameObject in self.gameObjects if gameObject.tag.tag == num]
else:
raise GameObjectException("No tag at index " + str(num) + "; create a new tag with Tag.AddTag")
[docs] def start_scripts(self):
"""
Start the scripts in the Scene.
"""
self.lastFrame = time()
for gameObject in self.gameObjects:
for component in gameObject.components:
if isinstance(component, Behaviour):
component.Start()
self.physics = any(
isinstance(
component, physics.Collider
) for component in gameObject.components for gameObject in self.gameObjects
)
if self.physics:
self.collManager = physics.CollManager()
self.collManager.AddPhysicsInfo(self)
[docs] def Start(self):
"""
Start the internal parts of the
Scene.
"""
self.lights = [
GL_LIGHT0,
GL_LIGHT1,
GL_LIGHT2,
GL_LIGHT3,
GL_LIGHT4,
GL_LIGHT5,
GL_LIGHT6,
GL_LIGHT7
]
glEnable(GL_DEPTH_TEST)
if config.faceCulling:
glEnable(GL_CULL_FACE)
glEnable(GL_LIGHTING)
light_num = 0
for gameObject in self.gameObjects:
light = gameObject.GetComponent(Light)
if light:
color = (light.intensity / 100, light.intensity / 100, light.intensity / 100, 1)
glLightfv(self.lights[light_num], GL_DIFFUSE, color)
glLightfv(self.lights[light_num], GL_SPECULAR, (1, 1, 1, 1))
glEnable(self.lights[light_num])
light_num += 1
glColorMaterial(GL_FRONT, GL_EMISSION)
glEnable(GL_COLOR_MATERIAL)
glClearColor(*self.mainCamera.clearColor)
glMatrixMode(GL_PROJECTION)
gluPerspective(
self.mainCamera.fov / config.size[0] * config.size[1],
config.size[0] / config.size[1],
self.mainCamera.near,
self.mainCamera.far)
glMatrixMode(GL_MODELVIEW)
self.start_scripts()
if os.environ["PYUNITY_DEBUG_MODE"] == "1":
print("Physics is", "on" if self.physics else "off")
print("Scene \"" + self.name + "\" has started")
[docs] def Run(self):
"""
Run the scene and create a window for it.
"""
self.windowProvider = config.windowProvider
self.window = self.windowProvider(config.size, self.name)
self.Start()
self.window.start(self.update)
[docs] def update_scripts(self):
for gameObject in self.gameObjects:
for component in gameObject.components:
if isinstance(component, Behaviour):
component.Update(max(time() - self.lastFrame, 0.001))
if self.physics:
self.collManager.Step(max(time() - self.lastFrame, 0.001))
self.lastFrame = time()
[docs] def update(self):
"""
Updating function to pass to the window provider.
"""
self.update_scripts()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
gluLookAt(
*(list(self.mainCamera.transform.position * Vector3(0, 0, -1))),
*(list(self.mainCamera.transform.position * Vector3(0, 0, -1) - Vector3.forward())),
0, 1, 0)
glRotatef(*self.mainCamera.transform.rotation.angleAxisPair)
light_num = 0
for gameObject in self.gameObjects:
light = gameObject.GetComponent(Light)
if light:
pos = (*(gameObject.transform.position * Vector3(0, 0, -1)), int(light.type))
glLightfv(self.lights[light_num], GL_POSITION, pos)
light_num += 1
for gameObject in self.gameObjects:
renderer = gameObject.GetComponent(MeshRenderer)
if renderer:
glPushMatrix()
self.transform(gameObject.transform)
renderer.render()
glPopMatrix()