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]; // 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); } }
/// <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]; 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); } }
public ElementFrame(GenericX xform, CompressedElement compXform, bool hasChanged, TransformElement transformElement) { this.xform = xform; this.compXform = compXform; this.hasChanged = hasChanged; this.transformElement = transformElement; }
public void OnStartInterpolate(Frame frame, bool lateArrival = false, bool midTeleport = false) { // Don't apply the transform for frame 0 updates. Those are for teleports and weapon fire. if (frame.frameid == 0) // && !frame.updateType.IsTeleport()) { return; } for (int eid = 0; eid < transformElements.Length; eid++) { TransformElement te = transformElements[eid]; // 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 && frame.elements[eid].transform.type == XType.NULL) { DebugX.Log(!DebugX.logInfo ? "" : (Time.time + " <b>Null Late Arrival - NOTE if you keep seeing this davin - remove this test otherwise </b> " + te.snapshot + " " + te.target)); continue; } te.Snapshot(frame, lateArrival, midTeleport); } }
public XElement(GenericX transform, CompressedElement compTrans, bool hasChanged, TransformElement transformElement) { this.transform = transform; this.compTrans = compTrans; this.hasChanged = hasChanged; this.transformElement = transformElement; }
public void NSTBitstreamMirrorFirst(Frame frame, ref UdpBitStream outstream, bool waitingForTeleportConfirm) { for (int eid = 0; eid < elementCount; ++eid) { TransformElement te = transformElements[eid]; te.MirrorToClients(ref outstream, frame, te.frames[frame.frameid].hasChanged); // masks[eid].GetBitInMask(frame.frameid)); } }
public void OnRewindGhostsToFrame(Frame frame) { for (int eid = 0; eid < elementCount; ++eid) { TransformElement te = transformElements[eid]; te.Apply(te.frames[frame.frameid].xform, te.rewindGO); } }
/// <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]; 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; } } }
/// <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"; } } }
public void OnTeleportApply(Frame frame) { for (int eid = 0; eid < transformElements.Length; eid++) { TransformElement te = transformElements[eid]; if (te.teleportOverride) { te.Teleport(frame.elements[eid].transform); } } }
public void OnSvrTeleportCmd() { for (int eid = 0; eid < transformElements.Length; eid++) { TransformElement te = transformElements[eid]; if (te.teleportOverride) { te.Teleport(); } } }
/// <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]; // TODO: this likely is only wired to work correctly with offtick if (te.teleportOverride) { te.Teleport(frame); } } }
/// <summary> /// Teleport all elements that are flagged with teleportOverride = true; /// </summary> public void OnRcvSvrTeleportCmd(Frame frame) { for (int eid = 0; eid < transformElements.Length; eid++) { TransformElement te = transformElements[eid]; // TODO: this likely is only wired to work correctly with offtick if (te.teleportOverride) { te.Teleport(frame.elements[eid].compTrans, frame.elements[eid].transform); } } }
//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]; //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); } } }
/// <summary> /// Apply all of the current transforms to this frames stored transforms. /// </summary> public void CaptureCurrentTransforms() { updateType = UpdateType.Teleport; rootBitCullLevel = BitCullingLevel.NoCulling; RootPos = nst.transform.position; for (int eid = 0; eid < tes.Length; eid++) { TransformElement te = tes[eid]; te.frames[frameid].xform = te.Localized; te.frames[frameid].compXform = te.Compress(); } }
/// <summary> /// Apply all of the current transforms to this frames stored transforms. /// </summary> public void CaptureCurrentTransforms() { updateType = UpdateType.Teleport; rootSendType = RootSendType.Full; RootPos = nst.transform.position; for (int eid = 0; eid < elements.Count; eid++) { TransformElement te = nstElementsEngine.transformElements[eid]; elements[eid].transform = te.Localized; elements[eid].compTrans = te.Compress(); } }
/// <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, GameObject rewindGo, int startFrameid, int endFrameId, float timeBeforeSnapshot, float remainder, bool applyToGhost) { for (int eid = 0; eid < elementCount; ++eid) { TransformElement te = transformElements[eid]; //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.rewindGO); } } }
public override void OnGUI(Rect r, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(r, label, property); 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"); elementType = property.FindPropertyRelative("elementType"); 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 = (ElementType)elementType.intValue == ElementType.Position; isRot = (ElementType)elementType.intValue == ElementType.Rotation; 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.EnumMaskPopup(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), typeLabel + " 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; 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; } }