IEnumerator LoadGame(GameDataReader reader)
    {
        int version = reader.Version;
        int count   = version <= 0 ? -version : reader.ReadInt();       //Genius (see below code)

        if (version >= 3)
        {
            Random.State state = reader.ReadRandomState();
            if (!_reseedOnLoad)
            {
                Random.state = state;
            }
            _creationSpeedSlider.value    = CreationSpeed = reader.ReadFloat();
            _creationProgress             = reader.ReadFloat();
            _destructionSpeedSlider.value = DestructionSpeed = reader.ReadFloat();
            _destructionProgress          = reader.ReadFloat();
        }
        yield return(LoadLevel(version < 2 ? 1 : reader.ReadInt()));

        if (version >= 3)
        {
            GameLevel.Current.Load(reader);
        }
        for (int i = 0; i < count; i++)
        {
            int factoryID  = version >= 5 ? reader.ReadInt() : 0;
            int shapeID    = version > 0 ? reader.ReadInt() : 0;
            int materialID = version > 0 ? reader.ReadInt() : 0;

            vShape instance = _shapeFactories[factoryID].Get(shapeID, materialID);
            instance.Load(reader);
            _shapes.Add(instance);
        }
    }
    private void CreatePools()
    {
        _pools = new List <vShape> [_prefabs.Length];
        for (int i = 0; i < _pools.Length; i++)
        {
            _pools[i] = new List <vShape>();
        }

        if (Application.isEditor)
        {
            _poolScene = SceneManager.GetSceneByName(name);
            if (_poolScene.isLoaded)
            {
                GameObject[] rootObjects = _poolScene.GetRootGameObjects();
                for (int i = 0; i < rootObjects.Length; i++)
                {
                    vShape pooledShape = rootObjects[i].GetComponent <vShape>();
                    if (!pooledShape.gameObject.activeSelf)
                    {
                        _pools[pooledShape.ShapeID].Add(pooledShape);
                    }
                }

                return;
            }
        }
        _poolScene = SceneManager.CreateScene(name);     //Cool
    }
    public void Reclaim(vShape shapeToRecycle)
    {
        if (shapeToRecycle.OriginFactory != this)
        {
            Debug.LogError("Tried to reclaim shape with wrong factory."); return;
        }

        if (_recycle)
        {
            if (_pools == null)
            {
                CreatePools();
            }
        }
        else
        {
            Destroy(shapeToRecycle.gameObject);
        }

        _pools[shapeToRecycle.ShapeID].Add(shapeToRecycle);
        shapeToRecycle.gameObject.SetActive(false);
    }
    public virtual vShape SpawnShape()
    {
        int    factoryIndex = Random.Range(0, _spawnConfig.Factories.Length);
        vShape shape        = _spawnConfig.Factories[factoryIndex].GetRandom();

        Transform t = shape.transform;

        t.localPosition = SpawnPoint;
        t.localRotation = Random.rotation;
        t.localScale    = Vector3.one * _spawnConfig.Scale.RandomValueInRange;

        //Color
        if (_spawnConfig.IsUniformColor)
        {
            shape.SetColor(_spawnConfig.Color.RandomInRange);
        }
        else
        {
            for (int i = 0; i < shape.ColorCount; i++)
            {
                shape.SetColor(_spawnConfig.Color.RandomInRange, i);
            }
        }

        float angularSpeed = _spawnConfig.AngularSpeed.RandomValueInRange;

        if (angularSpeed != 0f)         //If moving
        {
            var rotation = shape.AddBehavior <RotationShapeBehavior>();
            rotation.AngularVelocity =
                Random.onUnitSphere * _spawnConfig.AngularSpeed.RandomValueInRange;
        }

        float speed = _spawnConfig.Speed.RandomValueInRange;

        if (speed != 0f)
        {
            Vector3 direction;
            switch (_spawnConfig.movementDirection)
            {
            case SpawnConfiguration.MovementDirection.Upward:
                direction = transform.up;
                break;

            case SpawnConfiguration.MovementDirection.Outward:
                direction = (t.localPosition - transform.position).normalized;
                break;

            case SpawnConfiguration.MovementDirection.Random:
                direction = Random.onUnitSphere;
                break;

            default:
                direction = transform.forward;
                break;
            }

            var movement = shape.AddBehavior <MovementShapeBehavior>();
            movement.Velocity = direction * speed;
        }

        return(shape);
    }
 public override void GameUpdate(vShape shape)
 {
     shape.transform.localPosition += Velocity * Time.deltaTime;
 }
 public abstract void GameUpdate(vShape shape);
 public override void GameUpdate(vShape shape)
 {
     shape.transform.Rotate(AngularVelocity * Time.deltaTime);
 }