Esempio n. 1
0
 public ElementFrame(GenericX xform, CompressedElement compXform, bool hasChanged, TransformElement transformElement)
 {
     this.xform            = xform;
     this.compXform        = compXform;
     this.hasChanged       = hasChanged;
     this.transformElement = transformElement;
 }
Esempio n. 2
0
        /// <summary>
        /// Extrapolate is used when the buffer is empty.
        /// </summary>
        public void OnExtrapolate(Frame targFr, Frame currFr, int extrapolationCount, bool svrWaitingForTeleportConfirm)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                bool currIsNull = te.frames[currFr.frameid].xform.type == XType.NULL;

                // repeat teleportoverride if this is server and is waiting for a teleport confirm
                bool svrWaiting = svrWaitingForTeleportConfirm && te.teleportOverride;                 // || currFr.updateType.IsTeleport() && te.teleportOverride;

                // Don't extrapolate if this was a teleport or if we are exceeded the max number of sequential extrapolates
                bool dontExtrapolate = (currFr.updateType.IsTeleport() || extrapolationCount >= te.maxExtrapolates);

                te.frames[targFr.frameid].xform =
                    svrWaiting ? te.lastSentTransform :
                    dontExtrapolate ? currIsNull ? te.Localized : te.frames[currFr.frameid].xform :                     // If the current frame we are extrapolating was a teleport... just copy
                    te.Extrapolate();

                te.frames[targFr.frameid].compXform =
                    svrWaiting ? te.lastSentCompressed :
                    dontExtrapolate ? te.frames[currFr.frameid].compXform :                     // If the current frame we are extrapolating was a teleport... just copy
                    te.Compress(te.frames[targFr.frameid].xform);
            }
        }
Esempio n. 3
0
        public void OnStartInterpolate(Frame frame, bool lateArrival = false, bool midTeleport = false)
        {
            // Don't apply the transform for frame offtick updates. Those are for teleports and weapon fire.
            //TODO: Likely no longer needed, frame 0 shoud only fire onrcv
            //if (frame.frameid == 0)// && !frame.updateType.IsTeleport())
            //	return;

            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                // Don't overwrite mid interpolation if this is a teleport override element, and we are mid teleport.
                if (lateArrival && midTeleport && te.teleportOverride)
                {
                    continue;
                }

                // Don't modify elements with late arriving data if it is null.
                if (lateArrival && te.frames[frame.frameid].xform.type == XType.NULL)
                {
                    DebugX.Log(!DebugX.logInfo ? null :
                               (Time.time + " <b>Null Late Arrival - NOTE if you keep seeing this davin - remove this test otherwise </b> " + te.snapshotFrameId + " " + te.targetFrameId));

                    continue;
                }

                te.Snapshot(frame, lateArrival, midTeleport);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Make all TE names uqique... with a priority of changing the newly created one first.
        /// </summary>
        public static void MakeAllNamesUnique(GameObject go, TransformElement targetTe = null)
        {
            uniqueNames.Clear();

            // First add the selected gameobjects names to list - all but the last (should be the last added)
            INSTTransformElement[] iTransElement = go.GetComponents <INSTTransformElement>();

            // Determine if the last element has the name Unnamed... and presume it is a new item if so.
            TransformElement newElement =
                (targetTe != null) ? targetTe :
                (iTransElement.Length > 0 && iTransElement[iTransElement.Length - 1].TransElement.name == "Unnamed") ?
                iTransElement[iTransElement.Length - 1].TransElement :
                null;

            string holdname = (newElement != null) ? newElement.name : "";

            // Renmae it temporarily to make sure it doesn't conflict already.
            if (newElement != null)
            {
                newElement.name = "CRAZYPLACEHOLDERNAME";
            }

            // Then add all te names to the list - making them unique if any somehow failed to be
            iTransElement = go.transform.root.GetComponentsInChildren <INSTTransformElement>(true);

            for (int i = 0; i < iTransElement.Length; i++)
            {
                TransformElement te = iTransElement[i].TransElement;

                // Disallow empty names
                if (te.name == "")
                {
                    te.name = "Unnamed";
                }

                // Add zeros until the name is unique
                while (uniqueNames.Contains(te.name))
                {
                    te.name += "0";
                }

                uniqueNames.Add(te.name);
            }

            // Name the new element back to Unnamed, and add zeros until it is unique
            if (newElement != null)
            {
                newElement.name = holdname;
                while (uniqueNames.Contains(newElement.name))
                {
                    newElement.name += "0";
                }
            }
        }
Esempio n. 5
0
        public void OnSnapshotToRewind(Frame frame)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                te.history[frame.frameid] = te.Localized;
            }
        }
Esempio n. 6
0
        public void OnRewindGhostsToFrame(Frame frame)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                te.Apply(te.frames[frame.frameid].xform, te.ghostGO);
            }
        }
Esempio n. 7
0
        public void NSTBitstreamMirrorFirst(Frame frame, ref UdpBitStream outstream, bool waitingForTeleportConfirm)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                te.MirrorToClients(ref outstream, frame, te.frames[frame.frameid].hasChanged);                 // masks[eid].GetBitInMask(frame.frameid));
            }
        }
Esempio n. 8
0
        public void OnInterpolate(float t)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                te.UpdateInterpolation(t);
            }
        }
Esempio n. 9
0
        // callback from NST, extract transform elements
        public void NSTBitstreamIncomingFirst(Frame frame, Frame currFrame, ref UdpBitStream bitstream, bool isServer)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                te.frames[frame.frameid].hasChanged = te.Read(ref bitstream, frame, currFrame);
            }
        }
Esempio n. 10
0
        public void OnCreateGhost(GameObject srcGO, GameObject ghostGO)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                if (srcGO == te.gameobject)
                {
                    te.ghostGO = ghostGO;
                }
            }
        }
Esempio n. 11
0
        public void NSTBitstreamOutgoingFirst(Frame frame, ref UdpBitStream bitstream)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                te.Write(ref bitstream, frame);

                //// Write to the local buffer
                //te.frames[frame.frameid].xform = te.Localized;
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Apply all of the current transforms to this frames stored transforms.
        /// </summary>
        public void CaptureCurrentTransforms()
        {
            updateType       = UpdateType.Teleport;
            rootBitCullLevel = BitCullingLevel.NoCulling;

            RootPos = nst.cachedTransform.position;

            TransformElement[] tes = ee.transformElements;
            int count = tes.Length;

            for (int eid = 0; eid < count; eid++)
            {
                TransformElement te = tes[eid];

                te.frames[frameid].xform     = te.Localized;
                te.frames[frameid].compXform = te.Compress();
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Teleport all elements that are flagged with teleportOverride = true;
        /// </summary>
        public void OnRcvSvrTeleportCmd(Frame frame)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                // TODO: this likely is only wired to work correctly with offtick
                if (te.teleportOverride)
                {
                    te.Teleport(frame);
                }
            }
        }
Esempio n. 14
0
        //public void OnSvrTeleportCmd()
        //{
        //	for (int eid = 0; eid < elementCount; ++eid)
        //	{
        //		TransformElement te = transformElements[eid];
        //		if (te.teleportOverride)
        //			te.Teleport();
        //	}

        //}

        public void OnTeleportApply(Frame frame)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                //TODO this should be checking for the elements mask?
                // TODO: Uncertain about this check for null - should be testing for whether or not this element has any info to teleport with.
                if (te.teleportOverride)
                {
                    te.Teleport(frame);
                }
            }
        }
Esempio n. 15
0
        /// <summary>
        /// If a Rewind request has been made, this callback interface is called on all registered elements. Each element will populate its history[0] frame with the resuts of the requested rewind time.
        /// If applyToGhost is true, it will also apply its rewound result to its element on the rewindGhost for this NST.
        /// </summary>
        public void OnRewind(HistoryFrame fe, int startFrameid, int endFrameId, float timeBeforeSnapshot, float remainder, bool applyToGhost)
        {
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                //TODO: this needs to slerp for rotation types
                te.history[frameCount] = (timeBeforeSnapshot > 0) ?
                                         Vector3.Lerp(te.history[startFrameid], te.history[endFrameId], remainder) :
                                         Vector3.Lerp(te.history[startFrameid], te.Localized, -remainder);

                if (applyToGhost)
                {
                    te.Apply(te.history[frameCount], te.ghostGO);
                }
            }
        }
Esempio n. 16
0
        public NSTElementsEngine Initialize()
        {
            if (initialized)
            {
                return(this);
            }

            initialized = true;

            // This is redundant with the base class, but with initialize in Awake() rather than NSTAwake not assurance currently that it is set.
            nst = GetComponent <NetworkSyncTransform>();

            frameCount = 60 / nst.sendEveryXTick;

            // Collect all of the transform elements
            INSTTransformElement[] iTransElement = GetComponentsInChildren <INSTTransformElement>(true);
            elementCount = iTransElement.Length;

            elementIdLookup = new Dictionary <string, int>(elementCount);
            elementLookup   = new Dictionary <string, TransformElement>(elementCount);

            transformElements      = new TransformElement[elementCount];
            cache_elementIsEnabled = new bool[elementCount];

            for (int i = 0; i < elementCount; ++i)
            {
                TransformElement te = iTransElement[i].TransElement;

                cache_elementIsEnabled[i] =
                    te.sendCullMask != 0 &&
                    te.keyRate != 0 &&
                    te.crusher.Enabled;

                if (elementIdLookup.ContainsKey(te.name))
                {
                    DebugX.LogError(!DebugX.logErrors ? null :
                                    ("Multiple child elements with the same name on '" + nst.name + "'. Check the names of Rotation and Positon elements for any repeats and be sure they all have unique names."));
                }
                else
                {
                    elementIdLookup.Add(te.name, i);
                    elementLookup.Add(te.name, te);
                }


                //// Make note of which of the transforms belongs to the NST root rotation
                //if (System.Object.ReferenceEquals(te, nst.rootRotationElement))
                //{
                //	Debug.Log("ROOT NST ROTATION FOUND");
                //	//transformElements[0] = transformElements[i];
                //}

                transformElements[i]       = te;
                transformElements[i].index = i;

                if (transformElements[i].gameobject == null)
                {
                    transformElements[i].gameobject = iTransElement[i].SrcGameObject;
                }

                transformElements[i].Initialize(nst);

                //Debug.Log(nst.rootRotationElement.frames[0]);

                //// TODO: Questionable and stupid hack that replaces NST rootRotationElement with the found interface version (should be the same but arent)
                //if (iTransElement[i] is NetworkSyncTransform)
                //	nst.rootRotationElement = transformElements[i] as RotationElement;
            }


            // init the list
            //history = new GenericX[frameCount + 1][];
            //for (int frameid = 0; frameid < history.Length; frameid++)
            //{
            //	history[frameid] = new GenericX[transformElements.Length];
            //	for (int elementid = 0; elementid < transformElements.Length; elementid++)
            //	{
            //		history[frameid][elementid] = new GenericX();
            //	}
            //}

            //int numbOfElements = transformElements.Length;

            //elements = new List<XElement>[frameCount + 1];
            //for (int fid = 0; fid < elements.Length; fid++)
            //{
            //	elements[fid] = new List<XElement>(numbOfElements);
            //	List<XElement> frameElements = elements[fid];

            //	for (int eid = 0; eid < numbOfElements; eid++)
            //	{
            //		frameElements.Add(new XElement(
            //			transformElements[eid].Localized,
            //			transformElements[eid].Compress(),
            //			false,
            //			transformElements[eid]
            //			));
            //	}
            //}
            //elements = new List<XElement>(numbOfElements);


            return(this);
        }
Esempio n. 17
0
        /// <summary>
        /// Unlike Extrapolate - Reconstruct is used when the buffer isn't empty, but rather we are dealing with a lost packet while there is a future frame in the buffer.
        /// </summary>
        public void OnReconstructMissing(Frame nextFrame, Frame currentFrame, Frame nextValidFrame, float t, bool svrWaitingForTeleportConfirm)
        {
            //List<XElement> currFrameElements = elements[currentFrame.frameid];
            //List<XElement> nextFrameElements = elements[nextFrame.frameid];
            //List<XElement> nextValidFrameElements = elements[nextValidFrame.frameid];

            // Reconstruct missing frames
            for (int eid = 0; eid < elementCount; ++eid)
            {
                TransformElement te = transformElements[eid];

                if (!cache_elementIsEnabled[eid])
                {
                    continue;
                }

                TransformElement.ElementFrame ce  = te.frames[currentFrame.frameid];             // currFrameElements[eid];
                TransformElement.ElementFrame ne  = te.frames[nextFrame.frameid];                // nextFrameElements[eid];
                TransformElement.ElementFrame nve = te.frames[nextValidFrame.frameid];


                //TODO are these if's needed for the null checking? Keep an eye on this.
                // Eliminate any Null genericX values = they indicate no changes
                if (ce.xform.type == XType.NULL)
                {
                    ce.xform     = te.Localized;
                    ce.compXform = te.Compress(ce.xform);

                    Debug.Log("Current element is null");
                }

                if (nve.xform.type == XType.NULL)
                {
                    nve.xform = ce.xform;
                    //Debug.LogError("nextvalid element is null");
                }


                // If server his holding for teleport confirm, keep using the same teleport value
                if (svrWaitingForTeleportConfirm && te.teleportOverride)
                {
                    ne.xform     = te.lastSentTransform;
                    ne.compXform = te.lastSentCompressed;
                }
                // There is a future frame to use as a guess target
                else if (nve.xform.type != XType.NULL)                 // nst.buffer.masks[eid].GetBitInMask(nextValidFrame.frameid))
                {
                    ne.xform     = te.Lerp(ce.xform, nve.xform, t);
                    ne.compXform = te.Compress(ne.xform);
                }
                // There is no future frame.
                else
                {
                    if (ce.xform.type == XType.NULL)
                    {
                        Debug.Log("Houston we have a null here.");
                    }

                    ne.xform     = ce.xform;
                    ne.compXform = ce.compXform;
                }
            }
        }
Esempio n. 18
0
        public override void OnGUI(Rect r, SerializedProperty property, GUIContent label)
        {
            EditorGUI.BeginProperty(r, label, property);

            property.serializedObject.ApplyModifiedProperties();
            property.serializedObject.Update();

            var par = PropertyDrawerUtility.GetParent(property);

            GameObject parGO;

            // the parent may be an NST or a TransformElement
            if (par is NSTElementComponent)
            {
                parGO = (par as NSTElementComponent).gameObject;
            }
            else
            {
                parGO = (par as NetworkSyncTransform).gameObject;
            }

            TransformElement te = PropertyDrawerUtility.GetActualObjectForSerializedProperty <TransformElement>(fieldInfo, property);

            name             = property.FindPropertyRelative("name");
            isRoot           = property.FindPropertyRelative("isRoot");
            keyRate          = property.FindPropertyRelative("keyRate");
            sendCullMask     = property.FindPropertyRelative("sendCullMask");
            gameobject       = property.FindPropertyRelative("gameobject");
            extrapolation    = property.FindPropertyRelative("extrapolation");
            maxExtrapolates  = property.FindPropertyRelative("maxExtrapolates");
            teleportOverride = property.FindPropertyRelative("teleportOverride");

            isPos = (te is IPositionElement);
            isRot = (te is IRotationElement);

            string typeLabel = (isPos) ? "Position" :  (isRot) ? "Rotation" : "Scale";

            margin    = 4;
            realwidth = r.width + 16 - 4;
            colwidths = realwidth / 4f;

            colwidths = Mathf.Max(colwidths, 65);             // limit the smallest size so things like sliders aren't shrunk too small to draw.

            currentLine = r.yMin + margin * 2;

            Color headerblockcolor = (isPos ? positionHeaderBarColor : isRot ? rotationHeaderBarColor : scaleHeaderBarColor);

            if (!isRoot.boolValue)
            {
                EditorGUI.DrawRect(new Rect(margin + 3, r.yMin + 2 + 2, realwidth - 6, LINEHEIGHT + 8), headerblockcolor);
            }

            savedIndentLevel = EditorGUI.indentLevel;

            EditorGUI.indentLevel = 0;
            if (!isRoot.boolValue)
            {
                string headerLabel = typeLabel + " Element";

                EditorGUI.LabelField(new Rect(r.xMin, currentLine, colwidths * 4, LINEHEIGHT), new GUIContent(headerLabel), "WhiteBoldLabel");

                NSTElementComponentEditor.MakeAllNamesUnique(parGO, te);

                EditorGUI.PropertyField(new Rect(r.xMin, currentLine, r.width - 4, LINEHEIGHT), name, new GUIContent(" "));

                currentLine += LINEHEIGHT + 8;
            }
            // The only element that will be found on the root (the actual NST component) is rotation
            else
            {
                EditorGUI.LabelField(new Rect(r.xMin, currentLine, r.width, LINEHEIGHT), new GUIContent("Root Rotation Updates"), "BoldLabel");
                currentLine += LINEHEIGHT + 4;
            }
            EditorGUI.indentLevel = 0;

            // Section for Send Culling enum flags

            left                  = 13;
            realwidth            -= 16;
            sendCullMask.intValue = System.Convert.ToInt32(EditorGUI.EnumMaskField(new Rect(left, currentLine, realwidth, LINEHEIGHT), new GUIContent("Send On Events:"), (SendCullMask)sendCullMask.intValue));
            currentLine          += LINEHEIGHT + 4;

            if (!isRoot.boolValue)
            {
                EditorGUI.PropertyField(new Rect(left, currentLine, realwidth, LINEHEIGHT), gameobject, new GUIContent("GameObject:"));
                currentLine += LINEHEIGHT + 4;
            }

            if (((SendCullMask)sendCullMask.intValue).EveryTick() == false)
            {
                EditorGUI.PropertyField(new Rect(left, currentLine, realwidth, LINEHEIGHT), keyRate, new GUIContent("Key Every:"));
                currentLine += LINEHEIGHT + 2;
            }

            if (keyRate.intValue == 0 && sendCullMask.intValue == 0)
            {
                //noUpdates = true;
                EditorGUI.HelpBox(new Rect(left, currentLine, realwidth, 48), "Element Disabled. Select one or more 'Send On Events' event to trigger on, and/or set Key Every to a number greater than 0.", MessageType.Warning);
                currentLine += 50;

                property.serializedObject.ApplyModifiedProperties();
                return;
            }
            else
            {
                //noUpdates = false;

                EditorGUI.PropertyField(new Rect(left, currentLine, realwidth, LINEHEIGHT), extrapolation, new GUIContent("Extrapolation:"));
                currentLine += LINEHEIGHT + 2;

                EditorGUI.PropertyField(new Rect(left, currentLine, realwidth, LINEHEIGHT), maxExtrapolates, new GUIContent("Max Extrapolations:"));
                currentLine += LINEHEIGHT + 2;

                EditorGUI.PropertyField(new Rect(left, currentLine, realwidth, LINEHEIGHT), teleportOverride, new GUIContent("Teleport Override:"));
                currentLine += LINEHEIGHT + 2;
            }
            property.serializedObject.ApplyModifiedProperties();
            property.serializedObject.Update();

            SerializedProperty crusher = property.FindPropertyRelative("crusher");
            float ch = EditorGUI.GetPropertyHeight(crusher);

            EditorGUI.PropertyField(new Rect(r.xMin, currentLine - 2, r.width, ch), crusher);
            currentLine += ch;

            property.serializedObject.ApplyModifiedProperties();


            SerializedProperty drawerHeight = property.FindPropertyRelative("drawerHeight");

            // revert to original indent level.
            EditorGUI.indentLevel = savedIndentLevel;

            // Record the height of this instance of drawer
            drawerHeight.floatValue = currentLine - r.yMin;

            EditorGUI.EndProperty();
        }