//generates object metatada based on sim object's properties
        public override ObjectMetadata ObjectMetadataFromSimObjPhysics(SimObjPhysics simObj, bool isVisible)
        {
            DroneObjectMetadata objMeta = new DroneObjectMetadata();

            objMeta.isCaught         = this.GetComponent <DroneFPSAgentController>().isObjectCaught(simObj);
            objMeta.numSimObjHits    = simObj.numSimObjHit;
            objMeta.numFloorHits     = simObj.numFloorHit;
            objMeta.numStructureHits = simObj.numStructureHit;
            objMeta.lastVelocity     = simObj.lastVelocity;

            GameObject o = simObj.gameObject;

            objMeta.name       = o.name;
            objMeta.position   = o.transform.position;
            objMeta.rotation   = o.transform.eulerAngles;
            objMeta.objectType = Enum.GetName(typeof(SimObjType), simObj.Type);
            objMeta.receptacle = simObj.IsReceptacle;

            objMeta.openable = simObj.IsOpenable;
            if (objMeta.openable)
            {
                objMeta.isOpen = simObj.IsOpen;
            }

            objMeta.toggleable = simObj.IsToggleable;
            if (objMeta.toggleable)
            {
                objMeta.isToggled = simObj.IsToggled;
            }

            objMeta.breakable = simObj.IsBreakable;
            if (objMeta.breakable)
            {
                objMeta.isBroken = simObj.IsBroken;
            }

            objMeta.canFillWithLiquid = simObj.IsFillable;
            if (objMeta.canFillWithLiquid)
            {
                objMeta.isFilledWithLiquid = simObj.IsFilled;
            }

            objMeta.dirtyable = simObj.IsDirtyable;
            if (objMeta.dirtyable)
            {
                objMeta.isDirty = simObj.IsDirty;
            }

            objMeta.cookable = simObj.IsCookable;
            if (objMeta.cookable)
            {
                objMeta.isCooked = simObj.IsCooked;
            }

            //if the sim object is moveable or pickupable
            if (simObj.IsPickupable || simObj.IsMoveable)
            {
                //this object should report back mass and salient materials

                string [] salientMaterialsToString = new string [simObj.salientMaterials.Length];

                for (int i = 0; i < simObj.salientMaterials.Length; i++)
                {
                    salientMaterialsToString[i] = simObj.salientMaterials[i].ToString();
                }

                objMeta.salientMaterials = salientMaterialsToString;

                //record the mass unless the object was caught by the drone, which means the
                //rigidbody was disabled
                if (!objMeta.isCaught)
                {
                    objMeta.mass = simObj.Mass;
                }
            }



            //can this object change others to hot?
            objMeta.canChangeTempToHot = simObj.canChangeTempToHot;

            //can this object change others to cold?
            objMeta.canChangeTempToCold = simObj.canChangeTempToCold;

            objMeta.sliceable = simObj.IsSliceable;
            if (objMeta.sliceable)
            {
                objMeta.isSliced = simObj.IsSliced;
            }

            objMeta.canBeUsedUp = simObj.CanBeUsedUp;
            if (objMeta.canBeUsedUp)
            {
                objMeta.isUsedUp = simObj.IsUsedUp;
            }

            //object temperature to string
            objMeta.ObjectTemperature = simObj.CurrentObjTemp.ToString();

            objMeta.pickupable = simObj.PrimaryProperty == SimObjPrimaryProperty.CanPickup; //can this object be picked up?
            objMeta.isPickedUp = simObj.isPickedUp;                                         //returns true for if this object is currently being held by the agent

            objMeta.moveable = simObj.PrimaryProperty == SimObjPrimaryProperty.Moveable;

            objMeta.objectId = simObj.ObjectID;

            // TODO: using the isVisible flag on the object causes weird problems
            // in the multiagent setting, explicitly giving this information for now.
            objMeta.visible = isVisible;        //simObj.isVisible;

            objMeta.isMoving = simObj.inMotion; //keep track of if this object is actively moving

            if (simObj.PrimaryProperty == SimObjPrimaryProperty.CanPickup || simObj.PrimaryProperty == SimObjPrimaryProperty.Moveable)
            {
                objMeta.objectOrientedBoundingBox = GenerateObjectOrientedBoundingBox(simObj);
            }

            //return world axis aligned bounds for this sim object
            objMeta.axisAlignedBoundingBox = GenerateAxisAlignedBoundingBox(simObj);

            return(objMeta);
        }
        public override MetadataWrapper generateMetadataWrapper()
        {
            // AGENT METADATA
            DroneAgentMetadata agentMeta = new DroneAgentMetadata();

            agentMeta.name          = "agent";
            agentMeta.position      = transform.position;
            agentMeta.rotation      = transform.eulerAngles;
            agentMeta.cameraHorizon = m_Camera.transform.rotation.eulerAngles.x;
            if (agentMeta.cameraHorizon > 180)
            {
                agentMeta.cameraHorizon -= 360;
            }

            //New Drone Stuff for agentMeta
            agentMeta.LauncherPosition = GetLauncherPosition();

            // OTHER METADATA
            MetadataWrapper metaMessage = new MetadataWrapper();

            //For Drone controller, currentTime should be based on
            //fixed update passes so use DroneTimeSinceStart instead of TimeSinceStart
            metaMessage.currentTime = DroneTimeSinceStart();

            //agentMeta.FlightMode = FlightMode;
            metaMessage.agent     = agentMeta;
            metaMessage.sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
            metaMessage.objects   = this.generateObjectMetadata();
            //check scene manager to see if the scene's objects are at rest
            metaMessage.isSceneAtRest   = physicsSceneManager.isSceneAtRest;
            metaMessage.collided        = collidedObjects.Length > 0;
            metaMessage.collidedObjects = collidedObjects;
            metaMessage.screenWidth     = Screen.width;
            metaMessage.screenHeight    = Screen.height;
            metaMessage.cameraPosition  = m_Camera.transform.position;
            metaMessage.cameraOrthSize  = cameraOrthSize;
            cameraOrthSize                = -1f;
            metaMessage.fov               = m_Camera.fieldOfView;
            metaMessage.lastAction        = lastAction;
            metaMessage.lastActionSuccess = lastActionSuccess;
            metaMessage.errorMessage      = errorMessage;

            if (errorCode != ServerActionErrorCode.Undefined)
            {
                metaMessage.errorCode = Enum.GetName(typeof(ServerActionErrorCode), errorCode);
            }

            List <InventoryObject> ios = new List <InventoryObject>();

            if (ItemInHand != null)
            {
                SimObjPhysics   so = ItemInHand.GetComponent <SimObjPhysics>();
                InventoryObject io = new InventoryObject();
                io.objectId   = so.ObjectID;
                io.objectType = Enum.GetName(typeof(SimObjType), so.Type);
                ios.Add(io);
            }

            metaMessage.inventoryObjects = ios.ToArray();

            // HAND
            metaMessage.hand               = new HandMetadata();
            metaMessage.hand.position      = AgentHand.transform.position;
            metaMessage.hand.localPosition = AgentHand.transform.localPosition;
            metaMessage.hand.rotation      = AgentHand.transform.eulerAngles;
            metaMessage.hand.localRotation = AgentHand.transform.localEulerAngles;

            // EXTRAS
            metaMessage.reachablePositions   = reachablePositions;
            metaMessage.flatSurfacesOnGrid   = flatten3DimArray(flatSurfacesOnGrid);
            metaMessage.distances            = flatten2DimArray(distances);
            metaMessage.normals              = flatten3DimArray(normals);
            metaMessage.isOpenableGrid       = flatten2DimArray(isOpenableGrid);
            metaMessage.segmentedObjectIds   = segmentedObjectIds;
            metaMessage.objectIdsInBox       = objectIdsInBox;
            metaMessage.actionIntReturn      = actionIntReturn;
            metaMessage.actionFloatReturn    = actionFloatReturn;
            metaMessage.actionFloatsReturn   = actionFloatsReturn;
            metaMessage.actionStringsReturn  = actionStringsReturn;
            metaMessage.actionVector3sReturn = actionVector3sReturn;

            if (alwaysReturnVisibleRange)
            {
                metaMessage.visibleRange = visibleRange();
            }

            // Resetting things
            reachablePositions   = new Vector3[0];
            flatSurfacesOnGrid   = new float[0, 0, 0];
            distances            = new float[0, 0];
            normals              = new float[0, 0, 0];
            isOpenableGrid       = new bool[0, 0];
            segmentedObjectIds   = new string[0];
            objectIdsInBox       = new string[0];
            actionIntReturn      = 0;
            actionFloatReturn    = 0.0f;
            actionFloatsReturn   = new float[0];
            actionStringsReturn  = new string[0];
            actionVector3sReturn = new Vector3[0];

            return(metaMessage);
        }
Exemplo n.º 3
0
    //a variation of the CheckSpawnArea logic from InstantiatePrefabTest.cs, but filter out things specifically for stove tops
    //which are unique due to being placed close together, which can cause objects placed on them to overlap in super weird ways oh
    //my god it took like 2 days to figure this out it should have been so simple
    public bool StoveTopCheckSpawnArea(SimObjPhysics simObj, Vector3 position, Quaternion rotation, bool spawningInHand)
    {
        //print("stove check");
        int layermask;

        //first do a check to see if the area is clear

        //if spawning in the agent's hand, ignore collisions with the Agent
        if (spawningInHand)
        {
            layermask = 1 << 8;
        }

        //oh we are spawning it somehwere in the environment, we do need to make sure not to spawn inside the agent or the environment
        else
        {
            layermask = (1 << 8) | (1 << 10);
        }

        //simObj.transform.Find("Colliders").gameObject.SetActive(false);
        Collider[] objcols;
        //make sure ALL colliders of the simobj are turned off for this check - can't just turn off the Colliders child object because of objects like
        //laptops which have multiple sets of colliders, with one part moving...
        objcols = simObj.transform.GetComponentsInChildren <Collider>();

        foreach (Collider col in objcols)
        {
            if (col.gameObject.name != "BoundingBox")
            {
                col.enabled = false;
            }
        }

        //keep track of both starting position and rotation to reset the object after performing the check!
        Vector3    originalPos = simObj.transform.position;
        Quaternion originalRot = simObj.transform.rotation;

        //let's move the simObj to the position we are trying, and then change it's rotation to the rotation we are trying
        simObj.transform.position = position;
        simObj.transform.rotation = rotation;

        //now let's get the BoundingBox of the simObj as reference cause we need it to create the overlapbox
        GameObject  bb    = simObj.BoundingBox.transform.gameObject;
        BoxCollider bbcol = bb.GetComponent <BoxCollider>();

        #if UNITY_EDITOR
        m_Started = true;
        gizmopos  = bb.transform.TransformPoint(bbcol.center);
        //gizmopos = inst.transform.position;
        gizmoscale = bbcol.size;
        //gizmoscale = simObj.BoundingBox.GetComponent<BoxCollider>().size;
        gizmoquaternion = rotation;
        #endif

        //we need the center of the box collider in world space, we need the box collider size/2, we need the rotation to set the box at, layermask, querytrigger
        Collider[] hitColliders = Physics.OverlapBox(bb.transform.TransformPoint(bbcol.center),
                                                     bbcol.size / 2.0f, simObj.transform.rotation,
                                                     layermask, QueryTriggerInteraction.Ignore);

        //now check if any of the hit colliders were any object EXCEPT other stove top objects i guess
        bool result = true;

        if (hitColliders.Length > 0)
        {
            foreach (Collider col in hitColliders)
            {
                //if we hit some structure object like a stove top or countertop mesh, ignore it since we are snapping this to a specific position right here
                if (!col.GetComponentInParent <SimObjPhysics>())
                {
                    break;
                }

                //if any sim object is hit that is not a stove burner, then ABORT
                if (col.GetComponentInParent <SimObjPhysics>().Type != SimObjType.StoveBurner)
                {
                    result = false;
                    simObj.transform.position = originalPos;
                    simObj.transform.rotation = originalRot;

                    foreach (Collider yes in objcols)
                    {
                        if (yes.gameObject.name != "BoundingBox")
                        {
                            yes.enabled = true;
                        }
                    }

                    return(result);
                }
            }
        }

        //nothing hit in colliders, so we are good to spawn.
        foreach (Collider col in objcols)
        {
            if (col.gameObject.name != "BoundingBox")
            {
                col.enabled = true;
            }
        }

        simObj.transform.position = originalPos;
        simObj.transform.rotation = originalRot;
        return(result);       //we are good to spawn, return true
    }
Exemplo n.º 4
0
    void LateUpdate()
    {
        //check what objects in the scene are currently in motion
        //Rigidbody[] rbs = FindObjectsOfType(typeof(Rigidbody)) as Rigidbody[];
        foreach (Rigidbody rb in rbsInScene)
        {
            if (rb == null)
            {
                return;
            }

            //if this rigidbody is part of a SimObject, calculate rest using lastVelocity/currentVelocity comparisons
            if (rb.GetComponentInParent <SimObjPhysics>() && rb.transform.gameObject.activeSelf) // make sure the object is actually active, otherwise skip the check
            {
                SimObjPhysics sop = rb.GetComponentInParent <SimObjPhysics>();

                float currentVelocity = Math.Abs(rb.angularVelocity.sqrMagnitude + rb.velocity.sqrMagnitude);
                float accel           = (currentVelocity - sop.lastVelocity) / Time.fixedDeltaTime;

                if (Mathf.Abs(accel) <= 0.0001f)
                {
                    sop.inMotion = false;
                    //print(sop.transform.name + " should be sleeping");
                    //rb.Sleep(); maybe do something to ensure object has stopped moving, and reduce jitter
                }

                else
                {
                    //the rb's velocities are not 0, so it is in motion and the scene is not at rest
                    rb.GetComponentInParent <SimObjPhysics>().inMotion = true;
                    isSceneAtRest = false;
                    // #if UNITY_EDITOR
                    // print(rb.GetComponentInParent<SimObjPhysics>().name + " is still in motion!");
                    // #endif
                }
            }

            //this rigidbody is not a SimOBject, and might be a piece of a shattered sim object spawned in, or something
            else
            {
                if (rb.transform.gameObject.activeSelf)
                {
                    //is the rigidbody at non zero velocity? then the scene is not at rest
                    if (!(Math.Abs(rb.angularVelocity.sqrMagnitude +
                                   rb.velocity.sqrMagnitude) < 0.01))
                    {
                        isSceneAtRest = false;
                        //make sure the rb's drag values are not at 0 exactly
                        //if(rb.drag < 0.1f)
                        rb.drag += 0.01f;

                        //if(rb.angularDrag < 0.1f)
                        //rb.angularDrag = 1.5f;
                        rb.angularDrag += 0.01f;

                        #if UNITY_EDITOR
                        print(rb.transform.name + " is still in motion!");
                        #endif
                    }

                    //the velocities are small enough, assume object has come to rest and force this one to sleep
                    else
                    {
                        rb.drag        = 1.0f;
                        rb.angularDrag = 1.0f;
                    }

                    //if the shard/broken piece gets out of bounds somehow and begins falling forever, get rid of it with this check
                    if (rb.transform.position.y < -50f)
                    {
                        rb.transform.gameObject.SetActive(false);
                        //note: we might want to remove these from the list of rbs at some point but for now it'll be fine
                    }
                }
            }
        }
    }
Exemplo n.º 5
0
    //IMPORTANT INFO!//
    //The prefab MUST have a Bounding Box with zeroed out transform, rotation, and 1, 1, 1 scale
    //All adjustments to the Bounding Box must be done on the collider only using the
    //"Edit Collider" button if you need to change the size
    //this assumes that the BoundingBox transform is zeroed out according to the root transform of the prefab
    private bool CheckSpawnArea(SimObjPhysics simObj, Vector3 position, Quaternion rotation, bool spawningInHand,
                                bool generateLayout = false) // if calling via GenerateLayouts (see PhysicsSceneManager), should always return true
    {
        int layermask;

        //first do a check to see if the area is clear

        //if spawning in the agent's hand, ignore collisions with the Agent
        if (spawningInHand)
        {
            layermask = 1 << 8;
        }

        //oh we are spawning it somehwere in the environment, we do need to make sure not to spawn inside the agent or the environment
        else
        {
            layermask = (1 << 8) | (1 << 10);
        }


        //track original position and rotation in case we need to reset
        Vector3    originalPos = simObj.transform.position;
        Quaternion originalRot = simObj.transform.rotation;

        //move it into place so the bouding box is in the right spot to generate the overlap box later
        simObj.transform.position = position;
        simObj.transform.rotation = rotation;

        //now let's get the BoundingBox of the simObj as reference cause we need it to create the overlapbox
        GameObject  bb       = simObj.BoundingBox.transform.gameObject;
        BoxCollider bbcol    = bb.GetComponent <BoxCollider>();
        Vector3     bbCenter = bbcol.center;
        Vector3     bbCenterTransformPoint = bb.transform.TransformPoint(bbCenter);
        //keep track of all 8 corners of the OverlapBox
        List <Vector3> corners = new List <Vector3>();

        //bottom forward right
        corners.Add(bb.transform.TransformPoint(bbCenter + new Vector3(bbcol.size.x, -bbcol.size.y, bbcol.size.z) * 0.5f));
        //bottom forward left
        corners.Add(bb.transform.TransformPoint(bbCenter + new Vector3(-bbcol.size.x, -bbcol.size.y, bbcol.size.z) * 0.5f));
        //bottom back left
        corners.Add(bb.transform.TransformPoint(bbCenter + new Vector3(-bbcol.size.x, -bbcol.size.y, -bbcol.size.z) * 0.5f));
        //bottom back right
        corners.Add(bb.transform.TransformPoint(bbCenter + new Vector3(bbcol.size.x, -bbcol.size.y, -bbcol.size.z) * 0.5f));

        //top forward right
        corners.Add(bb.transform.TransformPoint(bbCenter + new Vector3(bbcol.size.x, bbcol.size.y, bbcol.size.z) * 0.5f));
        //top forward left
        corners.Add(bb.transform.TransformPoint(bbCenter + new Vector3(-bbcol.size.x, bbcol.size.y, bbcol.size.z) * 0.5f));
        //top back left
        corners.Add(bb.transform.TransformPoint(bbCenter + new Vector3(-bbcol.size.x, bbcol.size.y, -bbcol.size.z) * 0.5f));
        //top back right
        corners.Add(bb.transform.TransformPoint(bbCenter + new Vector3(bbcol.size.x, bbcol.size.y, -bbcol.size.z) * 0.5f));

        SpawnCorners = corners;

        #if UNITY_EDITOR
        m_Started = true;
        gizmopos  = bb.transform.TransformPoint(bbCenter);
        //gizmopos = inst.transform.position;
        gizmoscale = bbcol.size;
        //gizmoscale = simObj.BoundingBox.GetComponent<BoxCollider>().size;
        gizmoquaternion = rotation;
        #endif

        //move sim object back to it's original spot back so the overlap box doesn't hit it
        simObj.transform.position = originalPos;
        simObj.transform.rotation = originalRot;

        //we need the center of the box collider in world space, we need the box collider size/2, we need the rotation to set the box at, layermask, querytrigger
        Collider[] hitColliders = Physics.OverlapBox(bbCenterTransformPoint,
                                                     bbcol.size / 2.0f, simObj.transform.rotation,
                                                     layermask, QueryTriggerInteraction.Ignore);
        // print("trying to place " + simObj.transform.name + ", hitCollider length is: " + hitColliders.Length);
        // foreach(Collider c in hitColliders)
        // {
        //     if(c.GetComponentInParent<Rigidbody>())
        //     print(c.GetComponentInParent<Rigidbody>().transform.name);
        // }
        //if a collider was hit, then the space is not clear to spawn
        if (!generateLayout)
        {
            if (hitColliders.Length > 0)
            {
                return(false);
            }
        }
        return(true);
    }
Exemplo n.º 6
0
    //use action.randomseed for seed, use action.forceVisible for if objects shoudld ONLY spawn outside and not inside anything
    // //set forceVisible to true for if you want objects to only spawn in immediately visible receptacles.
    // public bool RandomSpawnRequiredSceneObjects(ServerAction action)
    // {
    //     return RandomSpawnRequiredSceneObjects(action.randomSeed, action.forceVisible, action.numPlacementAttempts, action.placeStationary, action.numDuplicatesOfType, action.excludedReceptacles);
    // }

    //place each object in the array of objects that should appear in this scene randomly in valid receptacles
    //seed- random seed used to pick locations
    //SpawnOnlyOutside - set to true to use only receptacles that are open innately (ie: tables, countertops, sinks) and not ones that require actions to open (drawer, cabinet etc.)
    //maxPlacementAttempts - the max number of times an object will attempt to be placed in within a receptacle
    //StaticPlacement - set to true if objects should be placed so they don't roll around after being repositioned
    //numDuplicatesOfType - used to duplicate the first instance of an object type found in a scene
    //excludedReceptacles -
    public bool RandomSpawnRequiredSceneObjects(
        int seed,
        bool SpawnOnlyOutside,
        int maxPlacementAttempts,
        bool StaticPlacement,
        ObjectTypeCount[] numDuplicatesOfType,
        List <SimObjType> excludedReceptacles
        )
    {
                #if UNITY_EDITOR
        var Masterwatch = System.Diagnostics.Stopwatch.StartNew();
                #endif

        if (RequiredObjects.Count == 0)
        {
                        #if UNITY_EDITOR
            Debug.Log("No objects in Required Objects array, please add them in editor");
                        #endif

            return(false);
        }

        //initialize Unity's random with seed
        UnityEngine.Random.InitState(seed);

        List <SimObjType> TypesOfObjectsPrefabIsAllowedToSpawnIn = new List <SimObjType>();
        Dictionary <SimObjType, List <SimObjPhysics> > AllowedToSpawnInAndExistsInScene = new Dictionary <SimObjType, List <SimObjPhysics> >();

        int HowManyCouldntSpawn = RequiredObjects.Count;

        //if we already spawned objects, lets just move them around
        if (SpawnedObjects.Count > 0)
        {
            HowManyCouldntSpawn = SpawnedObjects.Count;

            Dictionary <SimObjType, List <SimObjPhysics> > typeToObjectList = new Dictionary <SimObjType, List <SimObjPhysics> >();

            Dictionary <SimObjType, int> requestedNumDuplicatesOfType = new Dictionary <SimObjType, int>();
            //List<SimObjType> listOfExcludedReceptacles = new List<SimObjType>();
            HashSet <GameObject> originalObjects = new HashSet <GameObject>(SpawnedObjects);

            if (numDuplicatesOfType == null)
            {
                numDuplicatesOfType = new ObjectTypeCount[0];
            }
            foreach (ObjectTypeCount repeatCount in numDuplicatesOfType)
            {
                SimObjType objType = (SimObjType)System.Enum.Parse(typeof(SimObjType), repeatCount.objectType);
                requestedNumDuplicatesOfType[objType] = repeatCount.count;
            }

            //now lets go through all pickupable sim objects that are in the current scene
            foreach (GameObject go in SpawnedObjects)
            {
                SimObjPhysics sop = null;
                sop = go.GetComponent <SimObjPhysics>();

                //add object types in the current scene to the typeToObjectList if not already on it
                if (!typeToObjectList.ContainsKey(sop.ObjType))
                {
                    typeToObjectList[sop.ObjType] = new List <SimObjPhysics>();
                }

                //Add this sim object to the list if the sim object's type matches the key in typeToObjectList
                if (!requestedNumDuplicatesOfType.ContainsKey(sop.ObjType) ||
                    (typeToObjectList[sop.ObjType].Count < requestedNumDuplicatesOfType[sop.ObjType]))
                {
                    typeToObjectList[sop.ObjType].Add(sop);
                }
            }

            //keep track of the sim objects we are making duplicates of
            List <GameObject> simObjectDuplicates = new List <GameObject>();
            //keep track of the sim objects that have not been duplicated
            List <GameObject> unduplicatedSimObjects = new List <GameObject>();

            //ok now lets go through each object type in the dictionary
            foreach (SimObjType sopType in typeToObjectList.Keys)
            {
                //we found a matching SimObjType and the requested count of duplicates is bigger than how many of that
                //object are currently in the scene
                if (requestedNumDuplicatesOfType.ContainsKey(sopType) &&
                    requestedNumDuplicatesOfType[sopType] > typeToObjectList[sopType].Count)
                {
                    foreach (SimObjPhysics sop in typeToObjectList[sopType])
                    {
                        simObjectDuplicates.Add(sop.gameObject);
                    }

                    int numExtra = requestedNumDuplicatesOfType[sopType] - typeToObjectList[sopType].Count;

                    //let's instantiate the duplicates now
                    for (int j = 0; j < numExtra; j++)
                    {
                        // Add a copy of the item to try and match the requested number of duplicates
                        SimObjPhysics sop  = typeToObjectList[sopType][UnityEngine.Random.Range(0, typeToObjectList[sopType].Count - 1)];
                        SimObjPhysics copy = Instantiate(sop);
                        copy.name    += "_random_copy_" + j;
                        copy.ObjectID = sop.ObjectID + "_copy_" + j;
                        copy.objectID = copy.ObjectID;
                        simObjectDuplicates.Add(copy.gameObject);
                    }
                }

                //this object is not one that needs duplicates, so just add it to the unduplicatedSimObjects list
                else
                {
                    foreach (SimObjPhysics sop in typeToObjectList[sopType])
                    {
                        unduplicatedSimObjects.Add(sop.gameObject);
                    }
                }
            }

            unduplicatedSimObjects.Shuffle_(seed);
            simObjectDuplicates.AddRange(unduplicatedSimObjects);

            List <SimObjPhysics> ReceptaclesInScene = new List <SimObjPhysics>();
            ReceptaclesInScene = GatherAllReceptaclesInScene();

            //ok now simObjectDuplicates should have all the game objects, duplicated and unduplicated
            foreach (GameObject go in simObjectDuplicates)
            {
                AllowedToSpawnInAndExistsInScene = new Dictionary <SimObjType, List <SimObjPhysics> >();

                SimObjType goObjType = go.GetComponent <SimObjPhysics>().ObjType;

                bool typefoundindictionary = ReceptacleRestrictions.PlacementRestrictions.ContainsKey(goObjType);
                if (typefoundindictionary)
                {
                    TypesOfObjectsPrefabIsAllowedToSpawnIn = new List <SimObjType>(ReceptacleRestrictions.PlacementRestrictions[goObjType]);

                    //remove from list if receptacle isn't in this scene
                    //compare to receptacles that exist in scene, get the ones that are the same

                    foreach (SimObjPhysics sop in ReceptaclesInScene)
                    {
                        // don't random spawn in objects that are pickupable to prevent Egg spawning in Plate with the plate spawned in Cabinet....
                        bool allowed = false;
                        if (sop.PrimaryProperty != SimObjPrimaryProperty.CanPickup)
                        {
                            if (SpawnOnlyOutside)
                            {
                                if (ReceptacleRestrictions.SpawnOnlyOutsideReceptacles.Contains(sop.ObjType) && TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
                                {
                                    allowed = true;
                                }
                            }
                            else if (TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
                            {
                                allowed = true;
                            }
                        }

                        if (allowed)
                        {
                            if (!AllowedToSpawnInAndExistsInScene.ContainsKey(sop.ObjType))
                            {
                                AllowedToSpawnInAndExistsInScene[sop.ObjType] = new List <SimObjPhysics>();
                            }

                            AllowedToSpawnInAndExistsInScene[sop.ObjType].Add(sop);
                        }
                    }
                }

                //not found in dictionary!
                else
                {
                                        #if UNITY_EDITOR
                    Debug.Log(go.name + "'s Type is not in the ReceptacleRestrictions dictionary!");
                                        #endif
                    break;
                }

                // Now we have an updated list of receptacles in the scene that are also in the list
                // of valid receptacles for this given game object "go" that we are currently checking this loop
                if (AllowedToSpawnInAndExistsInScene.Count > 0)
                {
                    InstantiatePrefabTest       spawner = gameObject.GetComponent <InstantiatePrefabTest>();
                    List <ReceptacleSpawnPoint> targetReceptacleSpawnPoints;

                    bool spawned = false;
                    foreach (SimObjPhysics sop in ShuffleSimObjPhysicsDictList(AllowedToSpawnInAndExistsInScene, seed))
                    {
                        //if the receptacle, sop, is in the list of receptacles to exclude, skip over it and try the other Receptacles
                        if (excludedReceptacles.Contains(sop.Type))
                        {
                            continue;
                        }

                        //check if the target Receptacle is an ObjectSpecificReceptacle
                        //if so, if this game object is compatible with the ObjectSpecific restrictions, place it!
                        //this is specifically for things like spawning a mug inside a coffee maker
                        if (sop.DoesThisObjectHaveThisSecondaryProperty(SimObjSecondaryProperty.ObjectSpecificReceptacle))
                        {
                            ObjectSpecificReceptacle osr = sop.GetComponent <ObjectSpecificReceptacle>();

                            if (osr.HasSpecificType(go.GetComponent <SimObjPhysics>().ObjType))
                            {
                                //in the random spawn function, we need this additional check because there isn't a chance for
                                //the physics update loop to fully update osr.isFull() correctly, which can cause multiple objects
                                //to be placed on the same spot (ie: 2 pots on the same burner)
                                if (osr.attachPoint.transform.childCount > 0)
                                {
                                    break;
                                }

                                //perform additional checks if this is a Stove Burner!
                                if (sop.GetComponent <SimObjPhysics>().Type == SimObjType.StoveBurner)
                                {
                                    if (StoveTopCheckSpawnArea(go.GetComponent <SimObjPhysics>(), osr.attachPoint.transform.position,
                                                               osr.attachPoint.transform.rotation, false) == true)
                                    {
                                        //print("moving object now");
                                        go.transform.position = osr.attachPoint.position;
                                        go.transform.SetParent(osr.attachPoint.transform);
                                        go.transform.localRotation = Quaternion.identity;

                                        go.GetComponent <Rigidbody>().collisionDetectionMode = CollisionDetectionMode.Discrete;
                                        go.GetComponent <Rigidbody>().isKinematic            = true;

                                        HowManyCouldntSpawn--;
                                        spawned = true;

                                        break;
                                    }
                                }

                                //for everything else (coffee maker, toilet paper holder, etc) just place it if there is nothing attached
                                else
                                {
                                    go.transform.position = osr.attachPoint.position;
                                    go.transform.SetParent(osr.attachPoint.transform);
                                    go.transform.localRotation = Quaternion.identity;

                                    Rigidbody rb = go.GetComponent <Rigidbody>();
                                    rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
                                    rb.isKinematic            = true;

                                    HowManyCouldntSpawn--;
                                    spawned = true;
                                    break;
                                }
                            }
                        }

                        targetReceptacleSpawnPoints = sop.ReturnMySpawnPoints(false);

                        //first shuffle the list so it's raaaandom
                        targetReceptacleSpawnPoints.Shuffle_(seed);

                        if (spawner.PlaceObjectReceptacle(targetReceptacleSpawnPoints, go.GetComponent <SimObjPhysics>(), StaticPlacement, maxPlacementAttempts, 90, true))
                        {
                            HowManyCouldntSpawn--;
                            spawned = true;
                            break;
                        }
                    }

                    if (!spawned)
                    {
                                                #if UNITY_EDITOR
                        Debug.Log(go.name + " could not be spawned.");
                        #endif
                        //go.GetComponent<SimpleSimObj>().IsDisabled = true;
                        if (!originalObjects.Contains(go))
                        {
                            go.SetActive(false);
                            Destroy(go);
                        }
                    }
                }
            }
        }

        else
        {
            ///XXX: add exception in at some point
            throw new NotImplementedException();
        }

                #if UNITY_EDITOR
        if (HowManyCouldntSpawn > 0)
        {
            Debug.Log(HowManyCouldntSpawn + " object(s) could not be spawned into the scene!");
        }

        Masterwatch.Stop();
        var elapsed = Masterwatch.ElapsedMilliseconds;
        print("total time: " + elapsed);
                #endif

        SetupScene();
        return(true);
    }
Exemplo n.º 7
0
 //used to create object id for an object created as result of a state change of another object ie: bread - >breadslice1, breadslice 2 etc
 public void Generate_InheritedObjectID(SimObjPhysics sourceObject, SimObjPhysics createdObject, int count)
 {
     createdObject.ObjectID = sourceObject.ObjectID + "|" + createdObject.ObjType + "_" + count;
     AddToObjectsInScene(createdObject);
 }
Exemplo n.º 8
0
    private void LateUpdate()
    {
        int completeCount = 0;

        foreach (BaseFPSAgentController agent in this.agents)
        {
            if (agent.actionComplete)
            {
                completeCount++;
            }
        }

        //check what objects in the scene are currently in motion
        Rigidbody[] rbs = FindObjectsOfType(typeof(Rigidbody)) as Rigidbody[];
        foreach (Rigidbody rb in rbs)
        {
            //if this rigidbody is part of a SimObject, calculate rest using lastVelocity/currentVelocity comparisons
            if (rb.GetComponentInParent <SimObjPhysics>())
            {
                SimObjPhysics sop = rb.GetComponentInParent <SimObjPhysics>();

                float currentVelocity = Math.Abs(rb.angularVelocity.sqrMagnitude + rb.velocity.sqrMagnitude);
                float accel           = (currentVelocity - sop.lastVelocity) / Time.fixedDeltaTime;

                if (accel == 0)
                {
                    sop.inMotion = false;
                }

                else
                {
                    //the rb's velocities are not 0, so it is in motion and the scene is not at rest
                    rb.GetComponentInParent <SimObjPhysics>().inMotion = true;
                    physicsSceneManager.isSceneAtRest = false;
                }
            }

            //this rigidbody is not a SimOBject, and might be a piece of a shattered sim object spawned in, or something
            else
            {
                //is the rigidbody at non zero velocity? then the scene is not at rest
                if (!(Math.Abs(rb.angularVelocity.sqrMagnitude +
                               rb.velocity.sqrMagnitude) < 0.001))
                {
                    physicsSceneManager.isSceneAtRest = false;
                }
            }
        }

        if (completeCount == agents.Count && completeCount > 0 && readyToEmit)
        {
            readyToEmit = false;
            StartCoroutine(EmitFrame());
        }

        //ok now if the scene is at rest, turn back on physics autosimulation automatically
        //note: you can do this earlier by manually using the UnpausePhysicsAutoSim() action found in PhysicsRemoteFPSAgentController
        if (physicsSceneManager.isSceneAtRest &&
            physicsSceneManager.physicsSimulationPaused && AdvancePhysicsStepCount > 0)
        {
            //print("soshite toki wa ugoki desu");
            Physics.autoSimulation = true;
            physicsSceneManager.physicsSimulationPaused = false;
            AdvancePhysicsStepCount = 0;
        }
    }
Exemplo n.º 9
0
    //spawn receptacle/screen <objType> of index [variation] on <targetReceptacle> table object using random seed to pick which spawn coordinate used
    public bool SpawnExperimentObjAtRandom(string objType, int variation, int seed, SimObjPhysics targetReceptacle, float yRot = 0)
    {
        toSpawn = null;

        bool success = false;

        //init random state
        UnityEngine.Random.InitState(seed);

        if (objType == "screen")
        {
            toSpawn = screensToSpawn[variation].GetComponent <SimObjPhysics>();
        }

        if (objType == "receptacle")
        {
            toSpawn = receptaclesToSpawn[variation].GetComponent <SimObjPhysics>();
        }

        List <Vector3> spawnCoordinates          = new List <Vector3>();
        PhysicsRemoteFPSAgentController fpsAgent = agentManager.ReturnPrimaryAgent().GetComponent <PhysicsRemoteFPSAgentController>();

        spawnCoordinates = fpsAgent.GetSpawnCoordinatesAboveReceptacle(targetReceptacle);
        spawnCoordinates.Shuffle_(seed);

        //instantiate the prefab toSpawn away from every other object
        SimObjPhysics spawned = GameObject.Instantiate(toSpawn, initialSpawnPosition, Quaternion.identity);
        Rigidbody     rb      = spawned.GetComponent <Rigidbody>();

        //make sure object doesn't fall until we are done preparing to reposition it on the target receptacle
        rb.isKinematic = true;

        //apply rotation to object, default quaternion.identity
        spawned.transform.Rotate(new Vector3(0, yRot, 0), Space.Self);

        for (int i = 0; i < spawnCoordinates.Count; i++)
        {
            //place object at the given point, this also checks the spawn area to see if its clear
            //if not clear, it will return false
            if (fpsAgent.PlaceObjectAtPoint(toSpawn, spawnCoordinates[i]))
            {
                //we set success to true, if one of the corners doesn't fit on the table
                //this will be switched to false and will be returned at the end
                success = true;

                //double check if all corners of spawned object's bounding box are
                //above the targetReceptacle table
                //note this only accesses the very first receptacle trigger box, so
                //for EXPERIMENT ROOM TABLES make sure there is only one
                //receptacle trigger box on the square table
                List <Vector3> corners = GetCorners(spawned);

                Contains con         = targetReceptacle.ReceptacleTriggerBoxes[0].GetComponent <Contains>();
                bool     cornerCheck = true;
                foreach (Vector3 p in corners)
                {
                    if (!con.CheckIfPointIsAboveReceptacleTriggerBox(p))
                    {
                        cornerCheck = false;
                        //this position would cause object to fall off table
                        //double back and reset object to try again with another point
                        spawned.transform.position = initialSpawnPosition;
                        break;
                    }
                }

                if (!cornerCheck)
                {
                    success = false;
                    continue;
                }
            }

            //if all corners were succesful, break out of this loop, don't keep trying
            if (success)
            {
                rb.isKinematic = false;
                //run scene setup to grab reference to object and give it objectId
                sceneManager.SetupScene();
                sceneManager.ResetObjectIdToSimObjPhysics();
                break;
            }
        }

        //no objects could be spawned at any of the spawn points
        //destroy the thing we tried to place on target receptacle
        if (!success)
        {
            Destroy(spawned.transform.gameObject);
        }

        return(success);
    }
Exemplo n.º 10
0
 public void AddToObjectsInScene(SimObjPhysics sop)
 {
     UniqueIdToSimObjPhysics[sop.UniqueID] = sop;
 }
Exemplo n.º 11
0
    //return spawn coordinates above the <receptacleObjectId> that the <objectId> will fit at a given rotation <yRot>
    //excludes coordinates that would cause object <objectId> to fall off the table
    public List <Vector3> ReturnValidSpawns(string objType, int variation, SimObjPhysics targetReceptacle, float yRot = 0)
    {
        toSpawn = null;

        if (objType == "screen")
        {
            toSpawn = screensToSpawn[variation].GetComponent <SimObjPhysics>();
        }

        if (objType == "receptacle")
        {
            toSpawn = receptaclesToSpawn[variation].GetComponent <SimObjPhysics>();
        }

        SimObjPhysics spawned = GameObject.Instantiate(toSpawn, initialSpawnPosition, Quaternion.identity);
        Rigidbody     rb      = spawned.GetComponent <Rigidbody>();

        //apply rotation to object, default quaternion.identity
        spawned.transform.Rotate(new Vector3(0, yRot, 0), Space.Self);

        //generate grid of potential spawn points
        //GetSpawnCoordinatesAboveReceptacle
        List <Vector3> spawnCoordinates          = new List <Vector3>();
        PhysicsRemoteFPSAgentController fpsAgent = agentManager.ReturnPrimaryAgent().GetComponent <PhysicsRemoteFPSAgentController>();

        spawnCoordinates = fpsAgent.GetSpawnCoordinatesAboveReceptacle(targetReceptacle);

        List <Vector3> returnCoordinates = new List <Vector3>();

        //try and place object at every spawn coordinate and if it works, add it to the valid coords to return
        for (int i = 0; i < spawnCoordinates.Count; i++)
        {
            //place object at the given point, then check if the corners are ok
            fpsAgent.PlaceObjectAtPoint(toSpawn, spawnCoordinates[i]);

            List <Vector3> corners = GetCorners(spawned);

            Contains con         = targetReceptacle.ReceptacleTriggerBoxes[0].GetComponent <Contains>();
            bool     cornerCheck = true;
            foreach (Vector3 p in corners)
            {
                if (!con.CheckIfPointIsAboveReceptacleTriggerBox(p))
                {
                    cornerCheck = false;
                    //this position would cause object to fall off table
                    //double back and reset object to try again with another point
                    spawned.transform.position = initialSpawnPosition;
                    break;
                }
            }

            if (cornerCheck)
            {
                returnCoordinates.Add(spawnCoordinates[i]);
                //all corners were ok, so add it to the points that are valid
            }

            spawned.transform.position = initialSpawnPosition;
        }

        #if UNITY_EDITOR
        //debug draw
        debugCoords = returnCoordinates;
        #endif

        Destroy(spawned.transform.gameObject);
        return(returnCoordinates);
    }
Exemplo n.º 12
0
    //action to be called from PhysicsRemoteFPSAgentController
    public void Slice()
    {
        //if this is already sliced, we can't slice again so yeah stop that
        if (isSliced == true)
        {
            return;
        }

        //Disable this game object and spawn in the broken pieces
        Rigidbody rb = gameObject.GetComponent <Rigidbody>();

        rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
        rb.isKinematic            = true;

        //turn off everything except the top object, so we can continue to report back isSliced meta info without the object being "active"
        foreach (Transform t in gameObject.transform)
        {
            t.gameObject.SetActive(false);
        }

        GameObject resultObject;

        if (!gameObject.GetComponent <SimObjPhysics>().DoesThisObjectHaveThisSecondaryProperty(SimObjSecondaryProperty.CanBeCooked))
        {
            //instantiate the normal object if this object is not cooked, otherwise....
            resultObject = Instantiate(ObjectToChangeTo, transform.position, transform.rotation);
            isSliced     = true;
        }

        //if the object can be cooked, check if it is cooked and then spawn the cooked object to change to, otherwise spawn the normal object
        else
        {
            //instantiate the normal object if this object is not cooked, otherwise....
            resultObject = Instantiate(ObjectToChangeTo, transform.position, transform.rotation);
            isSliced     = true;

            if (gameObject.GetComponent <CookObject>().IsCooked())
            {
                //cook all objects under the resultObject
                foreach (Transform t in resultObject.transform)
                {
                    t.GetComponent <CookObject>().Cook();
                }
            }
        }


        PhysicsSceneManager psm = GameObject.Find("PhysicsSceneManager").GetComponent <PhysicsSceneManager>();

        if (psm != null)
        {
            //if the spawned object is not a sim object itself, but if it's holding a ton of sim objects let's go
            if (!resultObject.transform.GetComponent <SimObjPhysics>())
            {
                //each instantiated sliced version of the object is a bunch of sim objects held by a master parent transform, so go into each one and assign the id to each based on the parent's id so
                //there is an association with the original source object
                int count = 0;
                foreach (Transform t in resultObject.transform)
                {
                    SimObjPhysics tsop = t.GetComponent <SimObjPhysics>();
                    psm.Generate_InheritedObjectID(gameObject.GetComponent <SimObjPhysics>(), tsop, count);
                    count++;

                    //also turn on the kinematics of this object
                    Rigidbody trb = t.GetComponent <Rigidbody>();
                    trb.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
                    trb.isKinematic            = false;

                    //also add each child object's rb to the cache of all rigidbodies in scene
                    psm.AddToRBSInScene(trb);
                }
            }

            //the spawned object is a sim object itself, so make an ID for it
            else
            {
                //quick if the result object is an egg hard set it's rotation because EGGS ARE WEIRD and are not the same form as their shelled version
                if (resultObject.GetComponent <SimObjPhysics>().Type == SimObjType.EggCracked)
                {
                    resultObject.transform.rotation = Quaternion.Euler(Vector3.zero);
                }

                SimObjPhysics resultsop = resultObject.GetComponent <SimObjPhysics>();
                psm.Generate_InheritedObjectID(gameObject.GetComponent <SimObjPhysics>(), resultsop, 0);

                Rigidbody resultrb = resultsop.GetComponent <Rigidbody>();
                resultrb.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
                resultrb.isKinematic            = false;

                //also add the spawned object's RB to the cache of all rigidbodies in scene
                psm.AddToRBSInScene(resultrb);
            }
        }

        else
        {
            Debug.LogError("Physics Scene Manager object is missing from scene!");
        }

        //if image synthesis is active, make sure to update the renderers for image synthesis since now there are new objects with renderes in the scene
        BaseFPSAgentController primaryAgent = GameObject.Find("PhysicsSceneManager").GetComponent <AgentManager>().ReturnPrimaryAgent();

        if (primaryAgent.imageSynthesis)
        {
            if (primaryAgent.imageSynthesis.enabled)
            {
                primaryAgent.imageSynthesis.OnSceneChange();
            }
        }
    }
Exemplo n.º 13
0
    //place each object in the array of objects that should appear in this scene randomly in valid receptacles
    //a seed of 0 is the default positions placed by hand(?)
    public bool RandomSpawnRequiredSceneObjects(
        int seed,
        bool SpawnOnlyOutside,
        int maxPlacementAttempts,
        bool StaticPlacement,
        ObjectTypeCount[] numRepeats,
        ObjectTypeCount[] emptyReceptacleSpots
        )
    {
                #if UNITY_EDITOR
        var Masterwatch = System.Diagnostics.Stopwatch.StartNew();
                #endif

        if (RequiredObjects.Count == 0)
        {
                        #if UNITY_EDITOR
            Debug.Log("No objects in Required Objects array, please add them in editor");
                        #endif

            return(false);
        }

        UnityEngine.Random.InitState(seed);


        List <SimObjType> TypesOfObjectsPrefabIsAllowedToSpawnIn = new List <SimObjType>();
        Dictionary <SimObjType, List <SimObjPhysics> > AllowedToSpawnInAndExistsInScene = new Dictionary <SimObjType, List <SimObjPhysics> >();

        int HowManyCouldntSpawn = RequiredObjects.Count;

        // GameObject topLevelObject = GameObject.Find("Objects");
        // PhysicsRemoteFPSAgentController controller = GameObject.FindObjectsOfType<PhysicsRemoteFPSAgentController>()[0];

        // foreach (GameObject go in SpawnedObjects) {
        //  go.SetActive(true);
        //  SimObjPhysics sop = go.GetComponent<SimObjPhysics>();
        //  sop.transform.parent = topLevelObject.transform;
        //  sop.transform.position = new Vector3(0.0f, controller.sceneBounds.min.y - 10f, 0.0f);
        //  go.GetComponent<Rigidbody>().isKinematic = true;
        // }

        //if we already spawned objects, lets just move them around
        if (SpawnedObjects.Count > 0)
        {
            HowManyCouldntSpawn = SpawnedObjects.Count;

            //for each object in RequiredObjects, start a list of what objects it's allowed
            //to spawn in by checking the PlacementRestrictions dictionary

            Dictionary <SimObjType, List <SimObjPhysics> > typeToObjectList = new Dictionary <SimObjType, List <SimObjPhysics> >();

            List <GameObject>            simObjectCopies          = new List <GameObject>();
            List <GameObject>            unduplicatedSimObjects   = new List <GameObject>();
            Dictionary <SimObjType, int> requestedNumRepeats      = new Dictionary <SimObjType, int>();
            Dictionary <SimObjType, int> minFreePerReceptacleType = new Dictionary <SimObjType, int>();
            HashSet <GameObject>         originalObjects          = new HashSet <GameObject>(SpawnedObjects);

            if (numRepeats == null)
            {
                numRepeats = new ObjectTypeCount[0];
            }
            foreach (ObjectTypeCount repeatCount in numRepeats)
            {
                SimObjType objType = (SimObjType)System.Enum.Parse(typeof(SimObjType), repeatCount.objectType);
                requestedNumRepeats[objType] = repeatCount.count;
            }

            if (emptyReceptacleSpots == null)
            {
                emptyReceptacleSpots = new ObjectTypeCount[0];
            }
            foreach (ObjectTypeCount emptyReceptacleSpot in emptyReceptacleSpots)
            {
                SimObjType objType = (SimObjType)System.Enum.Parse(typeof(SimObjType), emptyReceptacleSpot.objectType);
                minFreePerReceptacleType[objType] = emptyReceptacleSpot.count;
            }

            foreach (GameObject go in SpawnedObjects)
            {
                SimObjPhysics gop = null;
                gop = go.GetComponent <SimObjPhysics>();
                if (!typeToObjectList.ContainsKey(gop.ObjType))
                {
                    typeToObjectList[gop.ObjType] = new List <SimObjPhysics>();
                }
                if (!requestedNumRepeats.ContainsKey(gop.ObjType) ||
                    (typeToObjectList[gop.ObjType].Count < requestedNumRepeats[gop.ObjType]))
                {
                    typeToObjectList[gop.ObjType].Add(gop);
                }
            }


            foreach (SimObjType sopType in typeToObjectList.Keys)
            {
                if (requestedNumRepeats.ContainsKey(sopType) &&
                    requestedNumRepeats[sopType] > typeToObjectList[sopType].Count)
                {
                    foreach (SimObjPhysics gop in typeToObjectList[sopType])
                    {
                        simObjectCopies.Add(gop.gameObject);
                    }
                    int numExtra = requestedNumRepeats[sopType] - typeToObjectList[sopType].Count;

                    for (int j = 0; j < numExtra; j++)
                    {
                        // Add a copy of the item.
                        SimObjPhysics gop  = typeToObjectList[sopType][UnityEngine.Random.Range(0, typeToObjectList[sopType].Count - 1)];
                        SimObjPhysics copy = Instantiate(gop);
                        copy.name    += "_random_copy_" + j;
                        copy.UniqueID = gop.UniqueID + "_copy_" + j;
                        copy.uniqueID = copy.UniqueID;
                        //Randomizer randomizer = (copy.gameObject.GetComponentInChildren<Randomizer>() as Randomizer);
                        //randomizer.Randomize(rnd.Next(0, 2147483647));
                        simObjectCopies.Add(copy.gameObject);
                    }
                }
                else
                {
                    foreach (SimObjPhysics gop in typeToObjectList[sopType])
                    {
                        unduplicatedSimObjects.Add(gop.gameObject);
                    }
                }
            }
            unduplicatedSimObjects.Shuffle_();
            simObjectCopies.AddRange(unduplicatedSimObjects);


            foreach (GameObject go in simObjectCopies)
            {
                AllowedToSpawnInAndExistsInScene = new Dictionary <SimObjType, List <SimObjPhysics> >();

                SimObjType goObjType = go.GetComponent <SimObjPhysics>().ObjType;

                bool typefoundindictionary = ReceptacleRestrictions.PlacementRestrictions.ContainsKey(goObjType);
                if (typefoundindictionary)
                {
                    TypesOfObjectsPrefabIsAllowedToSpawnIn = new List <SimObjType>(ReceptacleRestrictions.PlacementRestrictions[goObjType]);

                    //remove from list if receptacle isn't in this scene
                    //compare to receptacles that exist in scene, get the ones that are the same

                    // Todo: make a copy of receptacles and remove the ones where things can't be placed. Then clean up the placement code.
                    foreach (SimObjPhysics sop in ReceptaclesInScene)
                    {
                        // don't random spawn in objects that are pickupable to prevent Egg spawning in Plate with the plate spawned in Cabinet....
                        bool allowed = false;
                        if (sop.PrimaryProperty != SimObjPrimaryProperty.CanPickup)
                        {
                            if (SpawnOnlyOutside)
                            {
                                if (ReceptacleRestrictions.SpawnOnlyOutsideReceptacles.Contains(sop.ObjType) && TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
                                {
                                    allowed = true;
                                }
                            }
                            else if (TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
                            {
                                allowed = true;
                            }
                        }
                        if (allowed)
                        {
                            if (!AllowedToSpawnInAndExistsInScene.ContainsKey(sop.ObjType))
                            {
                                AllowedToSpawnInAndExistsInScene[sop.ObjType] = new List <SimObjPhysics>();
                            }
                            AllowedToSpawnInAndExistsInScene[sop.ObjType].Add(sop);
                        }
                    }
                }

                //not found in dictionary!
                else
                {
                                        #if UNITY_EDITOR
                    Debug.Log(go.name + "'s Type is not in the ReceptacleRestrictions dictionary!");
                                        #endif
                    break;
                }

                // Now we have an updated list of receptacles in the scene that are also in the list
                // of valid receptacles for this given game object "go" that we are currently checking this loop
                if (AllowedToSpawnInAndExistsInScene.Count > 0)
                {
                    //SimObjPhysics targetReceptacle;
                    InstantiatePrefabTest       spawner = gameObject.GetComponent <InstantiatePrefabTest>();
                    List <ReceptacleSpawnPoint> targetReceptacleSpawnPoints;

                    //each sop here is a valid receptacle
                    bool spawned = false;
                    foreach (SimObjPhysics sop in ShuffleSimObjPhysicsDictList(AllowedToSpawnInAndExistsInScene))
                    {
                        //targetReceptacle = sop;

                        //check if the target Receptacle is an ObjectSpecificReceptacle
                        //if so, if this game object is compatible with the ObjectSpecific restrictions, place it!
                        //this is specifically for things like spawning a mug inside a coffee maker
                        if (sop.DoesThisObjectHaveThisSecondaryProperty(SimObjSecondaryProperty.ObjectSpecificReceptacle))
                        {
                            ObjectSpecificReceptacle osr = sop.GetComponent <ObjectSpecificReceptacle>();

                            if (osr.HasSpecificType(go.GetComponent <SimObjPhysics>().ObjType))
                            {
                                //in the random spawn function, we need this additional check because there isn't a chance for
                                //the physics update loop to fully update osr.isFull() correctly, which can cause multiple objects
                                //to be placed on the same spot (ie: 2 pots on the same burner)
                                if (osr.attachPoint.transform.childCount > 0)
                                {
                                    break;
                                }

                                //perform additional checks if this is a Stove Burner!
                                if (sop.GetComponent <SimObjPhysics>().Type == SimObjType.StoveBurner)
                                {
                                    if (StoveTopCheckSpawnArea(go.GetComponent <SimObjPhysics>(), osr.attachPoint.transform.position,
                                                               osr.attachPoint.transform.rotation, false) == true)
                                    {
                                        //print("moving object now");
                                        go.transform.position = osr.attachPoint.position;
                                        go.transform.SetParent(osr.attachPoint.transform);
                                        go.transform.localRotation = Quaternion.identity;

                                        go.GetComponent <Rigidbody>().collisionDetectionMode = CollisionDetectionMode.Discrete;
                                        go.GetComponent <Rigidbody>().isKinematic            = true;

                                        HowManyCouldntSpawn--;
                                        spawned = true;

                                        // print(go.transform.name + " was spawned in " + sop.transform.name);

                                        // #if UNITY_EDITOR
                                        // //Debug.Log(go.name + " succesfully placed in " +sop.UniqueID);
                                        // #endif

                                        break;
                                    }
                                }

                                //for everything else (coffee maker, toilet paper holder, etc) just place it if there is nothing attached
                                else
                                {
                                    go.transform.position = osr.attachPoint.position;
                                    go.transform.SetParent(osr.attachPoint.transform);
                                    go.transform.localRotation = Quaternion.identity;

                                    Rigidbody rb = go.GetComponent <Rigidbody>();
                                    rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
                                    rb.isKinematic            = true;

                                    HowManyCouldntSpawn--;
                                    spawned = true;
                                    break;
                                }
                            }
                        }

                        targetReceptacleSpawnPoints = sop.ReturnMySpawnPoints(false);

                        //first shuffle the list so it's raaaandom
                        targetReceptacleSpawnPoints.Shuffle_();

                        //try to spawn it, and if it succeeds great! if not uhhh...

#if UNITY_EDITOR
                        // var watch = System.Diagnostics.Stopwatch.StartNew();
#endif

                        if (spawner.PlaceObjectReceptacle(targetReceptacleSpawnPoints, go.GetComponent <SimObjPhysics>(), StaticPlacement, maxPlacementAttempts, 90, true, minFreePerReceptacleType)) //we spawn them stationary so things don't fall off of ledges
                        {
                            HowManyCouldntSpawn--;
                            spawned = true;

                                                        #if UNITY_EDITOR
                            // watch.Stop();
                            // var y = watch.ElapsedMilliseconds;
                            //print( "SUCCESFULLY placing " + go.transform.name+ " in " + sop.transform.name);
                                                        #endif

                            break;
                        }

                                                #if UNITY_EDITOR
                        // watch.Stop();
                        // var elapsedMs = watch.ElapsedMilliseconds;
                        // print("time for trying, but FAILING, to place " + go.transform.name + " in " + sop.transform.name + ": " + elapsedMs + " ms");
                                                #endif
                    }

                    if (!spawned)
                    {
                                                #if UNITY_EDITOR
                        Debug.Log(go.name + " could not be spawned.");
                        #endif
                        //go.GetComponent<SimpleSimObj>().IsDisabled = true;
                        if (!originalObjects.Contains(go))
                        {
                            go.SetActive(false);
                            Destroy(go);
                        }
                    }
                }
            }
        }
        else
        {
            throw new NotImplementedException();
        }

        // Debug code to see where every object is spawning
        // string s = "";
        // foreach (GameObject sop in SpawnedObjects) {
        //  s += sop.name + ": " + sop.transform.parent.gameObject.name + ",\t";
        // }
        // Debug.Log(s);

        ///////////////KEEP THIS DEPRECATED STUFF - In case we want to spawn in objects that don't currently exist in the scene, that logic is below////////////////
        // //we have not spawned objects, so instantiate them here first
        // else
        // {
        //  //for each object in RequiredObjects, start a list of what objects it's allowed
        //  //to spawn in by checking the PlacementRestrictions dictionary
        //  foreach(GameObject go in RequiredObjects)
        //  {
        //      TypesOfObjectsPrefabIsAllowedToSpawnIn.Clear();
        //      AllowedToSpawnInAndExistsInScene.Clear();

        //      SimObjType goObjType = go.GetComponent<SimObjPhysics>().ObjType;

        //      bool typefoundindictionary = ReceptacleRestrictions.PlacementRestrictions.ContainsKey(goObjType);
        //      if(typefoundindictionary)
        //      {
        //          TypesOfObjectsPrefabIsAllowedToSpawnIn = new List<SimObjType>(ReceptacleRestrictions.PlacementRestrictions[goObjType]);

        //          //remove from list if receptacle isn't in this scene
        //          //compare to receptacles that exist in scene, get the ones that are the same

        //          foreach(SimObjPhysics sop in ReceptaclesInScene)
        //          {
        //              if(SpawnOnlyOutside)
        //              {
        //                  if(ReceptacleRestrictions.SpawnOnlyOutsideReceptacles.Contains(sop.ObjType) && TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
        //                  {
        //                      AllowedToSpawnInAndExistsInScene.Add(sop);
        //                  }
        //              }

        //              else if(TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
        //              {
        //                  //updated list of valid receptacles in scene
        //                  AllowedToSpawnInAndExistsInScene.Add(sop);
        //              }
        //          }
        //      }

        //      else
        //      {
        //          #if UNITY_EDITOR
        //          Debug.Log(go.name +"'s Type is not in the ReceptacleRestrictions dictionary!");
        //          #endif

        //          break;
        //      }

        //      // // //now we have an updated list of SimObjPhys of receptacles in the scene that are also in the list
        //      // // //of valid receptacles for this given game object "go" that we are currently checking this loop
        //      if(AllowedToSpawnInAndExistsInScene.Count > 0)
        //      {
        //          SimObjPhysics targetReceptacle;
        //          InstantiatePrefabTest spawner = gameObject.GetComponent<InstantiatePrefabTest>();
        //          List<ReceptacleSpawnPoint> targetReceptacleSpawnPoints;

        //          //RAAANDOM!
        //          ShuffleSimObjPhysicsList(AllowedToSpawnInAndExistsInScene);
        //          //bool diditspawn = false;


        //          GameObject temp = Instantiate(go, new Vector3(0, 100, 0), Quaternion.identity);
        //          temp.transform.name = go.name;
        //          //print("create object");
        //          //GameObject temp = PrefabUtility.InstantiatePrefab(go as GameObject) as GameObject;
        //          temp.GetComponent<Rigidbody>().isKinematic = true;
        //          //spawn it waaaay outside of the scene and then we will try and move it in a moment here, hold your horses
        //          temp.transform.position = new Vector3(0, 100, 0);//GameObject.Find("FPSController").GetComponent<PhysicsRemoteFPSAgentController>().AgentHandLocation();

        //          foreach(SimObjPhysics sop in AllowedToSpawnInAndExistsInScene)
        //          {
        //              targetReceptacle = sop;

        //              targetReceptacleSpawnPoints = targetReceptacle.ReturnMySpawnPoints(false);

        //              //first shuffle the list so it's raaaandom
        //              ShuffleReceptacleSpawnPointList(targetReceptacleSpawnPoints);

        //              //try to spawn it, and if it succeeds great! if not uhhh...

        //              #if UNITY_EDITOR
        //              var watch = System.Diagnostics.Stopwatch.StartNew();
        //              #endif

        //              if(spawner.PlaceObjectReceptacle(targetReceptacleSpawnPoints, temp.GetComponent<SimObjPhysics>(), true, maxcount, 360, true)) //we spawn them stationary so things don't fall off of ledges
        //              {
        //                  //Debug.Log(go.name + " succesfully spawned");
        //                  //diditspawn = true;
        //                  HowManyCouldntSpawn--;
        //                  SpawnedObjects.Add(temp);
        //                  break;
        //              }

        //              #if UNITY_EDITOR
        //              watch.Stop();
        //              var elapsedMs = watch.ElapsedMilliseconds;
        //              print("time for PlacfeObject: " + elapsedMs);
        //              #endif

        //          }
        //      }
        //  }
        // }

        //we can use this to report back any failed spawns if we want that info at some point ?

                #if UNITY_EDITOR
        if (HowManyCouldntSpawn > 0)
        {
            Debug.Log(HowManyCouldntSpawn + " object(s) could not be spawned into the scene!");
        }

        Masterwatch.Stop();
        var elapsed = Masterwatch.ElapsedMilliseconds;
        print("total time: " + elapsed);
                #endif

        //Debug.Log("Iteration through Required Objects finished");
        SetupScene();
        return(true);
    }
 public bool HasLaunch(SimObjPhysics obj)
 {
     return(DroneObjectLauncher.HasLaunch(obj));
 }
Exemplo n.º 15
0
 public void RemoveFromSpawnedObjects(SimObjPhysics sop)
 {
     SpawnedObjects.Remove(sop.gameObject);
 }
Exemplo n.º 16
0
        public void UpdateHighlightedObject(Vector3 screenPosition)
        {
            RaycastHit hit       = new RaycastHit();
            var        ray       = m_Camera.GetComponent <Camera>().ScreenPointToRay(screenPosition);
            int        layerMask = LayerMask.GetMask("SimObjVisible");

            Physics.Raycast(ray, out hit, this.MinHighlightDistance, layerMask);
            Debug.DrawLine(ray.origin, hit.point, Color.red);

            SimObjPhysics newHighlightedObject = null;
            Shader        newPreviousShader    = null;

            if (hit.transform != null &&
                hit.transform.tag == "SimObjPhysics" &&
                (this.PhysicsController.WhatAmIHolding() == null || this.highlightWhileHolding)
                )
            {
                softHighlight = true;
                var         simObj          = hit.transform.GetComponent <SimObjPhysics>();
                Func <bool> validObjectLazy = () => {
                    return((simObj.PrimaryProperty == SimObjPrimaryProperty.CanPickup && (this.onlyPickableObjectId == null || this.onlyPickableObjectId == simObj.uniqueID)) ||
                           simObj.GetComponent <CanOpen_Object>() ||
                           simObj.GetComponent <CanToggleOnOff>());
                };
                if (simObj != null && validObjectLazy())
                {
                    var withinReach = PhysicsController.FindObjectInVisibleSimObjPhysics(simObj.uniqueID) != null;
                    setTargetText(simObj.name, withinReach);
                    newHighlightedObject = simObj;
                    var mRenderer = newHighlightedObject.GetComponentInChildren <MeshRenderer>();

                    var useHighlightShader = !(disableHighlightShaderForObject && simObj.uniqueID == this.onlyPickableObjectId);

                    if (mRenderer != null && useHighlightShader)
                    {
                        if (this.highlightedObject != newHighlightedObject)
                        {
                            newPreviousShader              = mRenderer.material.shader;
                            this.previousRenderQueueValue  = mRenderer.material.renderQueue;
                            mRenderer.material.renderQueue = -1;
                            mRenderer.material.shader      = this.highlightShader;
                        }

                        if (withinReach)
                        {
                            softHighlight = true;
                            mRenderer.sharedMaterial.SetFloat("_Outline", this.HighlightParams.WithinReachOutlineThickness);
                            mRenderer.sharedMaterial.SetColor("_OutlineColor", this.HighlightParams.WithinReachOutlineColor);
                        }
                        else if (softHighlight)
                        {
                            softHighlight = false;
                            mRenderer.sharedMaterial.SetFloat("_Outline", this.HighlightParams.SoftOutlineThickness);
                            mRenderer.sharedMaterial.SetColor("_OutlineColor", this.HighlightParams.SoftOutlineColor);
                        }
                    }
                }
            }
            else
            {
                newHighlightedObject = null;
            }

            if (this.highlightedObject != newHighlightedObject && this.highlightedObject != null)
            {
                var mRenderer = this.highlightedObject.GetComponentInChildren <MeshRenderer>();

                setTargetText("");
                var useHighlightShader = !(disableHighlightShaderForObject && highlightedObject.uniqueID == this.onlyPickableObjectId);

                if (mRenderer != null && useHighlightShader)
                {
                    mRenderer.material.shader = this.previousShader;
                    // TODO unity has a bug for transparent objects they disappear when shader swapping, so we reset the previous shader's render queue value to render it appropiately.
                    mRenderer.material.renderQueue = this.previousRenderQueueValue;
                }
            }

            if (newPreviousShader != null)
            {
                this.previousShader = newPreviousShader;
            }


            this.highlightedObject = newHighlightedObject;
        }
Exemplo n.º 17
0
 public void RemoveFromRequiredObjects(SimObjPhysics sop)
 {
     RequiredObjects.Remove(sop.gameObject);
 }
Exemplo n.º 18
0
    public void OnSceneChange()
    {
        sentColorCorrespondence = false;
        var renderers = UnityEngine.Object.FindObjectsOfType <Renderer>();

        colorIds = new Dictionary <Color, string> ();
        var mpb = new MaterialPropertyBlock();

        foreach (var r in renderers)
        {
            // var layer = r.gameObject.layer;
            // var tag = r.gameObject.tag;

            string classTag = r.name;
            string objTag   = getObjectId(r.gameObject);

            StructureObject so = r.gameObject.GetComponent <StructureObject> ();
            if (so == null)
            {
                so = r.gameObject.GetComponentInParent <StructureObject> ();
            }

            SimObjPhysics sop = r.gameObject.GetComponent <SimObjPhysics> ();
            if (sop == null)
            {
                sop = r.gameObject.GetComponentInParent <SimObjPhysics> ();
            }

            if (so != null)
            {
                classTag = "" + so.WhatIsMyStructureObjectTag;
                //objTag = so.gameObject.name;
            }
            if (sop != null)
            {
                classTag = "" + sop.Type;
                objTag   = sop.ObjectID;
            }


            Color classColor = ColorEncoding.EncodeTagAsColor(classTag);
            Color objColor   = ColorEncoding.EncodeTagAsColor(objTag);

            capturePasses[0].camera.WorldToScreenPoint(r.bounds.center);

            if (so != null || sop != null)
            {
                colorIds [objColor]   = objTag;
                colorIds [classColor] = classTag;
            }

            else
            {
                colorIds [objColor] = r.gameObject.name;
            }

//			if (r.material.name.ToLower().Contains ("lightray")) {
//				objColor.a = 0;
//				classColor.a = 0;
//				mpb.SetFloat ("_Opacity", 0);
//
//			} else {
//				objColor.a = 1;
//				classColor.a = 1;
//				mpb.SetFloat ("_Opacity", 1);
//			}
//
            // updated per @danielg - replaces commented out code
            if (r.material.name.ToLower().Contains("lightray"))
            {
                r.enabled = false;
                continue;
            }

            objColor.a   = 1;
            classColor.a = 1;
            mpb.SetFloat("_Opacity", 1);
            mpb.SetColor("_CategoryColor", classColor);
            mpb.SetColor("_ObjectColor", objColor);

            r.SetPropertyBlock(mpb);
        }
    }
Exemplo n.º 19
0
    public bool PlaceObject(SimObjPhysics sop, ReceptacleSpawnPoint rsp, bool PlaceStationary, int degreeIncrement, bool AlwaysPlaceUpright, bool generateLayout = false)
    {
        if (rsp.ParentSimObjPhys == sop)
        {
            #if UNITY_EDITOR
            Debug.Log("Can't place object inside itself!");
            #endif
            return(false);
        }

        //remember the original rotation of the sim object if we need to reset it
        //Quaternion originalRot = sop.transform.rotation;
        Vector3    originalPos = sop.transform.position;
        Quaternion originalRot = sop.transform.rotation;

        //get the bounding box of the sim object we are trying to place
        BoxCollider oabb = sop.BoundingBox.GetComponent <BoxCollider>();

        //zero out rotation and velocity/angular velocity, then match the target receptacle's rotation
        sop.transform.rotation = rsp.ReceptacleBox.transform.rotation;
        Rigidbody sopRB = sop.GetComponent <Rigidbody>();
        sopRB.velocity        = Vector3.zero;
        sopRB.angularVelocity = Vector3.zero;


        //set 360 degree increment to only check one angle, set smaller increments to check more angles when trying to place (warning THIS WILL GET SLOWER)
        int   HowManyRotationsToCheck = 360 / degreeIncrement;
        Plane BoxBottom;
        float DistanceFromBoxBottomTosop;

        List <RotationAndDistanceValues> ToCheck = new List <RotationAndDistanceValues>(); //we'll check 8 rotations for now, replace the 45 later if we want to adjust the amount of checks

        //get rotations and distance values for 360/increment number of rotations around just the Y axis
        //we want to check all of these first so that the object is prioritized to be placed "upright"
        for (int i = 0; i < HowManyRotationsToCheck; i++)
        {
            oabb.enabled = true;

            if (i > 0)
            {
                sop.transform.Rotate(new Vector3(0, degreeIncrement, 0), Space.Self);
                //ToCheck[i].rotation = sop.transform.rotation;

                Vector3 Offset = oabb.ClosestPoint(oabb.transform.TransformPoint(oabb.center) + -rsp.ReceptacleBox.transform.up * 10);
                BoxBottom = new Plane(rsp.ReceptacleBox.transform.up, Offset);
                DistanceFromBoxBottomTosop = Math.Abs(BoxBottom.GetDistanceToPoint(sop.transform.position));

                ToCheck.Add(new RotationAndDistanceValues(DistanceFromBoxBottomTosop, sop.transform.rotation));
            }

            else
            {
                //no rotate change just yet, check the first position

                Vector3 Offset = oabb.ClosestPoint(oabb.transform.TransformPoint(oabb.center) + -rsp.ReceptacleBox.transform.up * 10); //was using rsp.point
                BoxBottom = new Plane(rsp.ReceptacleBox.transform.up, Offset);
                DistanceFromBoxBottomTosop = BoxBottom.GetDistanceToPoint(sop.transform.position);

                ToCheck.Add(new RotationAndDistanceValues(DistanceFromBoxBottomTosop, sop.transform.rotation));
            }

            oabb.enabled = false;
        }

        //continue to check rotations about the X and Z axes if the object doesn't have to be placed upright
        if (!AlwaysPlaceUpright)
        {
            //ok now try if the X and Z local axis are rotated if it'll fit
            //these values can cause the object to be placed at crazy angles, so we'll check these last
            for (int i = 0; i < HowManyRotationsToCheck; i++)
            {
                oabb.enabled = true;

                if (i > 0)
                {
                    sop.transform.Rotate(new Vector3(0, degreeIncrement, 0), Space.Self);
                    Quaternion oldRotation = sop.transform.rotation;

                    //now add more points by rotating the x axis at this current y rotation
                    for (int j = 0; j < HowManyRotationsToCheck; j++)
                    {
                        sop.transform.Rotate(new Vector3(degreeIncrement, 0, 0), Space.Self);

                        Vector3 Offset = oabb.ClosestPoint(oabb.transform.TransformPoint(oabb.center) + -rsp.ReceptacleBox.transform.up * 10);
                        BoxBottom = new Plane(rsp.ReceptacleBox.transform.up, Offset);
                        DistanceFromBoxBottomTosop = Math.Abs(BoxBottom.GetDistanceToPoint(sop.transform.position));

                        ToCheck.Add(new RotationAndDistanceValues(DistanceFromBoxBottomTosop, sop.transform.rotation));
                    }

                    sop.transform.rotation = oldRotation;

                    //now add EVEN more points by rotating the z axis at this current y rotation
                    for (int j = 0; j < HowManyRotationsToCheck; j++)
                    {
                        sop.transform.Rotate(new Vector3(0, 0, degreeIncrement), Space.Self);

                        Vector3 Offset = oabb.ClosestPoint(oabb.transform.TransformPoint(oabb.center) + -rsp.ReceptacleBox.transform.up * 10);
                        BoxBottom = new Plane(rsp.ReceptacleBox.transform.up, Offset);
                        DistanceFromBoxBottomTosop = Math.Abs(BoxBottom.GetDistanceToPoint(sop.transform.position));

                        ToCheck.Add(new RotationAndDistanceValues(DistanceFromBoxBottomTosop, sop.transform.rotation));
                    }

                    sop.transform.rotation = oldRotation;
                }

                oabb.enabled = false;
            }
        }


        foreach (RotationAndDistanceValues quat in ToCheck)
        {
            //if spawn area is clear, spawn it and return true that we spawned it
            if (CheckSpawnArea(sop, rsp.Point + rsp.ParentSimObjPhys.transform.up * (quat.distance + yoffset), quat.rotation, false, generateLayout))
            {
                //now to do a check to make sure the sim object is contained within the Receptacle box, and doesn't have
                //bits of it hanging out

                //Check the ReceptacleBox's Sim Object component to see what Type it is. Then check to
                //see if the type is the kind where the Object placed must be completely contained or just the bottom 4 corners contained
                int HowManyCornersToCheck = 0;
                if (ReceptacleRestrictions.OnReceptacles.Contains(rsp.ParentSimObjPhys.ObjType))
                {
                    //check that only the bottom 4 corners are in bounds
                    HowManyCornersToCheck = 4;
                }

                if (ReceptacleRestrictions.InReceptacles.Contains(rsp.ParentSimObjPhys.ObjType))
                {
                    //check that all 8 corners are within bounds
                    HowManyCornersToCheck = 8;
                }

                if (ReceptacleRestrictions.InReceptaclesThatOnlyCheckBottomFourCorners.Contains(rsp.ParentSimObjPhys.ObjType))
                {
                    //only check bottom 4 corners even though the action is PlaceIn
                    HowManyCornersToCheck = 4;
                }

                int CornerCount = 0;

                //Plane rspPlane = new Plane(rsp.Point, rsp.ParentSimObjPhys.transform.up);

                //now check the corner count for either the 4 lowest corners, or all 8 corners depending on Corner Count
                //attmpt to sort corners so that first four corners are the corners closest to the spawn point we are checking against
                SpawnCorners.Sort(delegate(Vector3 p1, Vector3 p2)
                {
                    //sort by making a plane where rsp.point is, find the four corners closest to that point
                    //return rspPlane.GetDistanceToPoint(p1).CompareTo(rspPlane.GetDistanceToPoint(p2));
                    //^ this ended up not working because if something is placed at an angle this no longer makes sense...

                    return(Vector3.Distance(p1, rsp.Point).CompareTo(Vector3.Distance(p2, rsp.Point)));

                    // return Vector3.Distance(new Vector3(0, p1.y, 0), new Vector3(0, rsp.Point.y, 0)).CompareTo(
                    // Vector3.Distance(new Vector3(0, p2.y, 0), new Vector3(0, rsp.Point.y, 0)));
                });

                //ok so this is just checking if there are enough corners in the Receptacle Zone to consider it placed correctly.
                //originally this looped up to i < HowManyCornersToCheck, but if we just check all the corners, regardless of
                //sort order, it seems to bypass the issue above of how to sort the corners to find the "bottom" 4 corners, so uh
                // i guess this might just work without fancy sorting to determine the bottom 4 corners... especially since the "bottom corners" starts to lose meaning as objects are rotated
                for (int i = 0; i < 8; i++)
                {
                    if (rsp.Script.CheckIfPointIsInsideReceptacleTriggerBox(SpawnCorners[i]))
                    {
                        CornerCount++;
                    }
                }

                //if not enough corners are inside the receptacle, abort
                if (CornerCount < HowManyCornersToCheck)
                {
                    sop.transform.rotation = originalRot;
                    sop.transform.position = originalPos;
                    return(false);
                }

                //one final check, make sure all corners of object are "above" the receptacle box in question, so we
                //dont spawn stuff half on a table and it falls over
                foreach (Vector3 v in SpawnCorners)
                {
                    if (!rsp.Script.CheckIfPointIsAboveReceptacleTriggerBox(v))
                    {
                        sop.transform.rotation = originalRot;
                        sop.transform.position = originalPos;
                        return(false);
                    }
                }

                //we passed all the checks! Place the object now!
                GameObject topObject = GameObject.Find("Objects");
                //parent to the Objects transform
                sop.transform.SetParent(topObject.transform);
                //translate position of the target sim object to the rsp.Point and offset in local y up
                sop.transform.position = rsp.Point + rsp.ReceptacleBox.transform.up * (quat.distance + yoffset);//rsp.Point + sop.transform.up * DistanceFromBottomOfBoxToTransform;
                sop.transform.rotation = quat.rotation;

                //set true if we want objects to be stationary when placed. (if placed on uneven surface, object remains stationary)
                //if false, once placed the object will resolve with physics (if placed on uneven surface object might slide or roll)
                if (PlaceStationary == true)
                {
                    //if place stationary make sure to set this object as a child of the parent receptacle in case it moves (like a drawer)
                    sop.GetComponent <Rigidbody>().isKinematic = true;

                    //check if the parent sim object is one that moves like a drawer - and would require this to be parented
                    //if(rsp.ParentSimObjPhys.DoesThisObjectHaveThisSecondaryProperty(SimObjSecondaryProperty.CanOpen))
                    sop.transform.SetParent(rsp.ParentSimObjPhys.transform);
                }

                else
                {
                    sop.GetComponent <Rigidbody>().isKinematic = false;
                }

                //if this object is a receptacle and it has other objects inside it, drop them all together
                if (sop.DoesThisObjectHaveThisSecondaryProperty(SimObjSecondaryProperty.Receptacle))
                {
                    PhysicsRemoteFPSAgentController agent = GameObject.Find("FPSController").GetComponent <PhysicsRemoteFPSAgentController>();
                    agent.DropContainedObjects(sop);
                }

                #if UNITY_EDITOR
                //Debug.Log(sop.name + " succesfully spawned in " +rsp.ParentSimObjPhys.name + " at coordinate " + rsp.Point);
                #endif

                return(true);
            }
        }

        //reset rotation if no valid spawns found
        //sop.transform.rotation = originalRot;
        //oh now we couldn't spawn it, all the spawn areas were not clear
        sop.transform.rotation = originalRot;
        sop.transform.position = originalPos;
        return(false);
    }