private void alpha_WhenTextChanged(object sender, EventArgs e) { if (preventchanges) { return; } MakeUndo(); //mxd int i = 0; //restore values if (string.IsNullOrEmpty(alpha.Text)) { foreach (Thing t in things) { UniFields.SetFloat(t.Fields, "alpha", thingprops[i++].Alpha, 1.0); } } else //update values { foreach (Thing t in things) { double value = General.Clamp(alpha.GetResultFloat(t.Fields.GetValue("alpha", 1.0)), 0.0, 1.0); UniFields.SetFloat(t.Fields, "alpha", value, 1.0); } } resetalpha.Visible = (alpha.GetResultFloat(1.0) != 1.0); General.Map.IsChanged = true; if (OnValuesChanged != null) { OnValuesChanged(this, EventArgs.Empty); } }
//mxd. Texture scale change protected override void ChangeTextureScale(int incrementX, int incrementY) { if (Texture == null || !Texture.IsImageLoaded) { return; } Sector s = GetControlSector(); float scaleX = s.Fields.GetValue("xscalefloor", 1.0f); float scaleY = s.Fields.GetValue("yscalefloor", 1.0f); s.Fields.BeforeFieldsChange(); if (incrementX != 0) { float pix = (int)Math.Round(Texture.Width * scaleX) - incrementX; float newscaleX = (float)Math.Round(pix / Texture.Width, 3); scaleX = (newscaleX == 0 ? scaleX * -1 : newscaleX); UniFields.SetFloat(s.Fields, "xscalefloor", scaleX, 1.0f); } if (incrementY != 0) { float pix = (int)Math.Round(Texture.Height * scaleY) - incrementY; float newscaleY = (float)Math.Round(pix / Texture.Height, 3); scaleY = (newscaleY == 0 ? scaleY * -1 : newscaleY); UniFields.SetFloat(s.Fields, "yscalefloor", scaleY, 1.0f); } mode.SetActionResult("Floor scale changed to " + scaleX.ToString("F03", CultureInfo.InvariantCulture) + ", " + scaleY.ToString("F03", CultureInfo.InvariantCulture) + " (" + (int)Math.Round(Texture.Width / scaleX) + " x " + (int)Math.Round(Texture.Height / scaleY) + ")."); }
//mxd public virtual void OnChangeTextureRotation(float angle) { if (!General.Map.UDMF) { return; } if ((General.Map.UndoRedo.NextUndo == null) || (General.Map.UndoRedo.NextUndo.TicketID != undoticket)) { undoticket = mode.CreateUndo("Change texture rotation"); } string key = (GeometryType == VisualGeometryType.FLOOR ? "rotationfloor" : "rotationceiling"); mode.SetActionResult((GeometryType == VisualGeometryType.FLOOR ? "Floor" : "Ceiling") + " rotation changed to " + angle); //set value Sector s = GetControlSector(); s.Fields.BeforeFieldsChange(); UniFields.SetFloat(s.Fields, key, angle, 0.0f); if (s.Index != Sector.Sector.Index) { s.UpdateNeeded = true; s.UpdateCache(); mode.GetSectorData(s).Update(); BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(s); vs.UpdateSectorGeometry(false); } Sector.Sector.UpdateNeeded = true; Sector.Sector.UpdateCache(); Sector.UpdateSectorGeometry(false); }
//mxd. Only control sidedef scale is used by GZDoom public override void OnChangeScale(int incrementX, int incrementY) { if (!General.Map.UDMF || Texture == null || !Texture.IsImageLoaded) { return; } if ((General.Map.UndoRedo.NextUndo == null) || (General.Map.UndoRedo.NextUndo.TicketID != undoticket)) { undoticket = mode.CreateUndo("Change wall scale"); } Sidedef target = extrafloor.Linedef.Front; if (target == null) { return; } float scaleX = target.Fields.GetValue("scalex_mid", 1.0f); float scaleY = target.Fields.GetValue("scaley_mid", 1.0f); target.Fields.BeforeFieldsChange(); if (incrementX != 0) { float pix = (int)Math.Round(Texture.Width * scaleX) - incrementX; float newscaleX = (float)Math.Round(pix / Texture.Width, 3); scaleX = (newscaleX == 0 ? scaleX * -1 : newscaleX); UniFields.SetFloat(target.Fields, "scalex_mid", scaleX, 1.0f); } if (incrementY != 0) { float pix = (int)Math.Round(Texture.Height * scaleY) - incrementY; float newscaleY = (float)Math.Round(pix / Texture.Height, 3); scaleY = (newscaleY == 0 ? scaleY * -1 : newscaleY); UniFields.SetFloat(target.Fields, "scaley_mid", scaleY, 1.0f); } // Update the model sector to update all 3d floors mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false); // Display result mode.SetActionResult("Wall scale changed to " + scaleX.ToString("F03", CultureInfo.InvariantCulture) + ", " + scaleY.ToString("F03", CultureInfo.InvariantCulture) + " (" + (int)Math.Round(Texture.Width / scaleX) + " x " + (int)Math.Round(Texture.Height / scaleY) + ")."); }
//mxd. Texture scale change protected override void ChangeTextureScale(int incrementX, int incrementY) { if (Texture == null || !Texture.IsImageLoaded) { return; } Sector s = GetControlSector(); float scaleX = s.Fields.GetValue("xscalefloor", 1.0f); float scaleY = s.Fields.GetValue("yscalefloor", 1.0f); s.Fields.BeforeFieldsChange(); if (incrementX != 0) { float pix = (int)Math.Round(Texture.Width * scaleX) - incrementX; float newscaleX = (float)Math.Round(pix / Texture.Width, 3); scaleX = (newscaleX == 0 ? scaleX * -1 : newscaleX); UniFields.SetFloat(s.Fields, "xscalefloor", scaleX, 1.0f); } if (incrementY != 0) { float pix = (int)Math.Round(Texture.Height * scaleY) - incrementY; float newscaleY = (float)Math.Round(pix / Texture.Height, 3); scaleY = (newscaleY == 0 ? scaleY * -1 : newscaleY); UniFields.SetFloat(s.Fields, "yscalefloor", scaleY, 1.0f); } // Update geometry if (mode.VisualSectorExists(level.sector)) { BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector); vs.UpdateSectorGeometry(false); } s.UpdateNeeded = true; s.UpdateCache(); if (s.Index != Sector.Sector.Index) { Sector.Sector.UpdateNeeded = true; Sector.Sector.UpdateCache(); } mode.SetActionResult("Floor scale changed to " + scaleX.ToString("F03", CultureInfo.InvariantCulture) + ", " + scaleY.ToString("F03", CultureInfo.InvariantCulture) + " (" + (int)Math.Round(Texture.Width / scaleX) + " x " + (int)Math.Round(Texture.Height / scaleY) + ")."); }
//mxd public virtual void OnChangeTextureRotation(float angle) { if (!General.Map.UDMF) { return; } if ((General.Map.UndoRedo.NextUndo == null) || (General.Map.UndoRedo.NextUndo.TicketID != undoticket)) { undoticket = mode.CreateUndo("Change texture rotation"); } string key = (GeometryType == VisualGeometryType.FLOOR ? "rotationfloor" : "rotationceiling"); mode.SetActionResult((GeometryType == VisualGeometryType.FLOOR ? "Floor" : "Ceiling") + " rotation changed to " + angle); // Set new angle Sector s = GetControlSector(); s.Fields.BeforeFieldsChange(); UniFields.SetFloat(s.Fields, key, angle, 0.0f); // Mark as changed changed = true; // Rebuild sector BaseVisualSector vs; if (mode.VisualSectorExists(level.sector)) { vs = (BaseVisualSector)mode.GetVisualSector(level.sector); } else { //mxd. Need this to apply changes to 3d-floor even if control sector doesn't exist as BaseVisualSector vs = mode.CreateBaseVisualSector(level.sector); } if (vs != null) { vs.UpdateSectorGeometry(false); } }
public void ApplyTo(UniFields fields, int min, int max, float oldValue1, float oldValue2) { if (!string.IsNullOrEmpty(value1.Text)) { UniFields.SetFloat(fields, field1, General.Clamp(value1.GetResultFloat(oldValue1), min, max), defaultValue); } else { UniFields.SetFloat(fields, field1, oldValue1, defaultValue); } if (!string.IsNullOrEmpty(value2.Text)) { UniFields.SetFloat(fields, field2, General.Clamp(value2.GetResultFloat(oldValue2), min, max), defaultValue); } else { UniFields.SetFloat(fields, field2, oldValue2, defaultValue); } }
//mxd protected void AlignTextureToSlopeLine(Linedef slopeSource, float slopeAngle, bool isFront, bool alignx, bool aligny) { bool isFloor = (geometrytype == VisualGeometryType.FLOOR); Sector.Sector.Fields.BeforeFieldsChange(); float sourceAngle = (float)Math.Round(General.ClampAngle(isFront ? -Angle2D.RadToDeg(slopeSource.Angle) + 90 : -Angle2D.RadToDeg(slopeSource.Angle) - 90), 1); if (isFloor) { if ((isFront && slopeSource.Front.Sector.FloorHeight > slopeSource.Back.Sector.FloorHeight) || (!isFront && slopeSource.Front.Sector.FloorHeight < slopeSource.Back.Sector.FloorHeight)) { sourceAngle = General.ClampAngle(sourceAngle + 180); } } else { if ((isFront && slopeSource.Front.Sector.CeilHeight < slopeSource.Back.Sector.CeilHeight) || (!isFront && slopeSource.Front.Sector.CeilHeight > slopeSource.Back.Sector.CeilHeight)) { sourceAngle = General.ClampAngle(sourceAngle + 180); } } //update angle UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "rotationfloor" : "rotationceiling"), sourceAngle, 0f); //update scaleY string xScaleKey = (isFloor ? "xscalefloor" : "xscaleceiling"); string yScaleKey = (isFloor ? "yscalefloor" : "yscaleceiling"); float scaleX = Sector.Sector.Fields.GetValue(xScaleKey, 1.0f); float scaleY; //set scale if (aligny) { scaleY = (float)Math.Round(scaleX * (1 / (float)Math.Cos(slopeAngle)), 2); UniFields.SetFloat(Sector.Sector.Fields, yScaleKey, scaleY, 1.0f); } else { scaleY = Sector.Sector.Fields.GetValue(yScaleKey, 1.0f); } //update texture offsets Vector2D offset; if (isFloor) { if ((isFront && slopeSource.Front.Sector.FloorHeight < slopeSource.Back.Sector.FloorHeight) || (!isFront && slopeSource.Front.Sector.FloorHeight > slopeSource.Back.Sector.FloorHeight)) { offset = slopeSource.End.Position; } else { offset = slopeSource.Start.Position; } } else { if ((isFront && slopeSource.Front.Sector.CeilHeight > slopeSource.Back.Sector.CeilHeight) || (!isFront && slopeSource.Front.Sector.CeilHeight < slopeSource.Back.Sector.CeilHeight)) { offset = slopeSource.End.Position; } else { offset = slopeSource.Start.Position; } } offset = offset.GetRotated(Angle2D.DegToRad(sourceAngle)); if (alignx) { if (Texture != null && Texture.IsImageLoaded) { offset.x %= Texture.Width / scaleX; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xpanningfloor" : "xpanningceiling"), (float)Math.Round(-offset.x), 0f); } if (aligny) { if (Texture != null && Texture.IsImageLoaded) { offset.y %= Texture.Height / scaleY; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "ypanningfloor" : "ypanningceiling"), (float)Math.Round(offset.y), 0f); } //update geometry Sector.UpdateSectorGeometry(false); }
//mxd protected void AlignTextureToClosestLine(bool alignx, bool aligny) { if (!(mode.HighlightedObject is BaseVisualSector)) { return; } // Do we need to align this? (and also grab texture scale while we are at it) float scaleX, scaleY; bool isFloor = (geometrytype == VisualGeometryType.FLOOR); if (mode.HighlightedTarget is VisualFloor) { VisualFloor target = (VisualFloor)mode.HighlightedTarget; // Check texture if (target.Sector.Sector.FloorTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Sector.Sector.Fields.GetValue("xscalefloor", 1.0f); scaleY = target.Sector.Sector.Fields.GetValue("yscalefloor", 1.0f); } else { VisualCeiling target = (VisualCeiling)mode.HighlightedTarget; // Check texture if (target.Sector.Sector.CeilTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Sector.Sector.Fields.GetValue("xscaleceiling", 1.0f); scaleY = target.Sector.Sector.Fields.GetValue("yscaleceiling", 1.0f); } //find a linedef to align to Vector2D hitpos = mode.GetHitPosition(); if (!hitpos.IsFinite()) { return; } //align to line of highlighted sector, which is closest to hitpos Sector highlightedSector = ((BaseVisualSector)mode.HighlightedObject).Sector; List <Linedef> lines = new List <Linedef>(); foreach (Sidedef side in highlightedSector.Sidedefs) { lines.Add(side.Line); } Linedef targetLine = MapSet.NearestLinedef(lines, hitpos); if (targetLine == null) { return; } bool isFront = targetLine.SideOfLine(hitpos) > 0; Sector.Sector.Fields.BeforeFieldsChange(); //find an angle to rotate texture float sourceAngle = (float)Math.Round(General.ClampAngle(isFront ? -Angle2D.RadToDeg(targetLine.Angle) + 90 : -Angle2D.RadToDeg(targetLine.Angle) - 90), 1); if (!isFront) { sourceAngle = General.ClampAngle(sourceAngle + 180); } //update angle UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "rotationfloor" : "rotationceiling"), sourceAngle, 0f); //set scale UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xscalefloor" : "xscaleceiling"), scaleX, 1.0f); UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "yscalefloor" : "yscaleceiling"), scaleY, 1.0f); //update offset float distToStart = Vector2D.Distance(hitpos, targetLine.Start.Position); float distToEnd = Vector2D.Distance(hitpos, targetLine.End.Position); Vector2D offset = (distToStart < distToEnd ? targetLine.Start.Position : targetLine.End.Position).GetRotated(Angle2D.DegToRad(sourceAngle)); if (alignx) { if (Texture != null && Texture.IsImageLoaded) { offset.x %= Texture.Width / scaleX; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xpanningfloor" : "xpanningceiling"), (float)Math.Round(-offset.x), 0f); } if (aligny) { if (Texture != null && Texture.IsImageLoaded) { offset.y %= Texture.Height / scaleY; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "ypanningfloor" : "ypanningceiling"), (float)Math.Round(offset.y), 0f); } //update geometry Sector.UpdateSectorGeometry(false); }
// Apply clicked private void apply_Click(object sender, EventArgs e) { //mxd. Make Undo MakeUndo(); List <string> defaultflags = new List <string>(); // Verify the tag if (General.Map.FormatInterface.HasThingTag) //mxd { tagSelector.ValidateTag(); //mxd if (((tagSelector.GetTag(0) < General.Map.FormatInterface.MinTag) || (tagSelector.GetTag(0) > General.Map.FormatInterface.MaxTag))) { General.ShowWarningMessage("Thing tag must be between " + General.Map.FormatInterface.MinTag + " and " + General.Map.FormatInterface.MaxTag + ".", MessageBoxButtons.OK); return; } } // Verify the type if (!string.IsNullOrEmpty(thingtype.TypeStringValue) && ((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType))) { General.ShowWarningMessage("Thing type must be between " + General.Map.FormatInterface.MinThingType + " and " + General.Map.FormatInterface.MaxThingType + ".", MessageBoxButtons.OK); return; } // Verify the action if (General.Map.FormatInterface.HasThingAction && ((action.Value < General.Map.FormatInterface.MinAction) || (action.Value > General.Map.FormatInterface.MaxAction))) { General.ShowWarningMessage("Thing action must be between " + General.Map.FormatInterface.MinAction + " and " + General.Map.FormatInterface.MaxAction + ".", MessageBoxButtons.OK); return; } // Go for all the things int offset = 0; //mxd foreach (Thing t in things) { // Coordination //mxd. Randomize rotations? if (cbrandomangle.Checked) { int newangle = General.Random(0, 359); if (General.Map.Config.DoomThingRotationAngles) { newangle = newangle / 45 * 45; } t.Rotate(newangle); } if (cbrandompitch.Checked) { t.SetPitch(General.Random(0, 359)); } if (cbrandomroll.Checked) { t.SetRoll(General.Random(0, 359)); } //mxd. Check position double px = General.Clamp(t.Position.x, General.Map.Config.LeftBoundary, General.Map.Config.RightBoundary); double py = General.Clamp(t.Position.y, General.Map.Config.BottomBoundary, General.Map.Config.TopBoundary); if (t.Position.x != px || t.Position.y != py) { t.Move(new Vector2D(px, py)); } // Action/tags t.Tag = General.Clamp(tagSelector.GetSmartTag(t.Tag, offset), General.Map.FormatInterface.MinTag, General.Map.FormatInterface.MaxTag); //mxd if (!action.Empty) { t.Action = action.Value; } //mxd. Apply args argscontrol.Apply(t, offset); //mxd. Custom fields fieldslist.Apply(t.Fields); if (!string.IsNullOrEmpty(conversationID.Text)) { UniFields.SetInteger(t.Fields, "conversation", conversationID.GetResult(t.Fields.GetValue("conversation", 0)), 0); } if (!string.IsNullOrEmpty(floatbobphase.Text)) { UniFields.SetInteger(t.Fields, "floatbobphase", General.Clamp(floatbobphase.GetResult(t.Fields.GetValue("floatbobphase", -1)), -1, 63), -1); } if (!string.IsNullOrEmpty(gravity.Text)) { UniFields.SetFloat(t.Fields, "gravity", gravity.GetResultFloat(t.Fields.GetValue("gravity", 1.0)), 1.0); } if (!string.IsNullOrEmpty(health.Text)) { UniFields.SetInteger(t.Fields, "health", health.GetResult(t.Fields.GetValue("health", 1)), 1); } if (!string.IsNullOrEmpty(score.Text)) { UniFields.SetInteger(t.Fields, "score", score.GetResult(t.Fields.GetValue("score", 0)), 0); } //mxd. User vars. Should be called after fieldslist.Apply() ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type); if (ti != null && ti.Actor != null && ti.Actor.UserVars.Count > 0) { fieldslist.ApplyUserVars(ti.Actor.UserVars, t.Fields); } color.ApplyTo(t.Fields, t.Fields.GetValue("fillcolor", 0)); //mxd. Comments commenteditor.Apply(t.Fields); // Update settings t.UpdateConfiguration(); //mxd. Increase offset... offset++; } // Set as defaults foreach (CheckBox c in flags.Checkboxes) { if (c.CheckState == CheckState.Checked) { defaultflags.Add(c.Tag.ToString()); } } General.Settings.DefaultThingType = thingtype.GetResult(General.Settings.DefaultThingType); General.Settings.DefaultThingAngle = Angle2D.DegToRad((float)angle.GetResult((int)Angle2D.RadToDeg(General.Settings.DefaultThingAngle) - 90) + 90); General.Settings.SetDefaultThingFlags(defaultflags); // Done General.Map.IsChanged = true; if (OnValuesChanged != null) { OnValuesChanged(this, EventArgs.Empty); //mxd } this.DialogResult = DialogResult.OK; this.Close(); }
//mxd protected void AlignTextureToClosestLine(bool alignx, bool aligny) { if (!(mode.HighlightedObject is BaseVisualSector)) { return; } // Do we need to align this? (and also grab texture scale while we are at it) float scaleX, scaleY; bool isFloor = (geometrytype == VisualGeometryType.FLOOR); if (mode.HighlightedTarget is VisualFloor) { Sector target; VisualFloor vf = (VisualFloor)mode.HighlightedTarget; // Use the control sector if the floor belongs to a 3D floor if (vf.ExtraFloor == null) { target = vf.Sector.Sector; } else { target = vf.GetControlSector(); } // Check texture if (target.FloorTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Fields.GetValue("xscalefloor", 1.0f); scaleY = target.Fields.GetValue("yscalefloor", 1.0f); } else { Sector target; VisualCeiling vc = (VisualCeiling)mode.HighlightedTarget; // Use the control sector if the ceiling belongs to a 3D floor if (vc.ExtraFloor == null) { target = vc.Sector.Sector; } else { target = vc.GetControlSector(); } // Check texture if (target.CeilTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Fields.GetValue("xscaleceiling", 1.0f); scaleY = target.Fields.GetValue("yscaleceiling", 1.0f); } //find a linedef to align to Vector2D hitpos = mode.GetHitPosition(); if (!hitpos.IsFinite()) { return; } //align to line of highlighted sector, which is closest to hitpos Sector highlightedSector = ((BaseVisualSector)mode.HighlightedObject).Sector; List <Linedef> lines = new List <Linedef>(); foreach (Sidedef side in highlightedSector.Sidedefs) { lines.Add(side.Line); } Linedef targetLine = MapSet.NearestLinedef(lines, hitpos); if (targetLine == null) { return; } bool isFront = targetLine.SideOfLine(hitpos) > 0; Sector.Sector.Fields.BeforeFieldsChange(); //find an angle to rotate texture float sourceAngle = (float)Math.Round(General.ClampAngle(isFront ? -Angle2D.RadToDeg(targetLine.Angle) + 90 : -Angle2D.RadToDeg(targetLine.Angle) - 90), 1); if (!isFront) { sourceAngle = General.ClampAngle(sourceAngle + 180); } //update angle UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "rotationfloor" : "rotationceiling"), sourceAngle, 0f); // Scale texture if it's a slope and the appropriate option is set if (level.plane.Normal.z != 1.0f && BuilderPlug.Me.ScaleTexturesOnSlopes != 2) { Vector2D basescale = new Vector2D(1.0f, 1.0f); // User wants to use the current scale as a base? if (BuilderPlug.Me.ScaleTexturesOnSlopes == 1) { basescale.x = scaleX; basescale.y = scaleY; } // Create a unit vector of the direction of the target line in 3D space Vector3D targetlinevector = new Line3D(new Vector3D(targetLine.Start.Position, level.plane.GetZ(targetLine.Start.Position)), new Vector3D(targetLine.End.Position, level.plane.GetZ(targetLine.End.Position))).GetDelta().GetNormal(); // Get a perpendicular vector of the target line in 3D space. This is used to get the slope angle relative to the target line Vector3D targetlineperpendicular = Vector3D.CrossProduct(targetlinevector, level.plane.Normal); if (alignx) { scaleX = Math.Abs(basescale.x * (1.0f / (float)Math.Cos(targetlinevector.GetAngleZ()))); } if (aligny) { scaleY = Math.Abs(basescale.y * (1.0f / (float)Math.Cos(targetlineperpendicular.GetAngleZ()))); } } //set scale UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xscalefloor" : "xscaleceiling"), scaleX, 1.0f); UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "yscalefloor" : "yscaleceiling"), scaleY, 1.0f); //update offset float distToStart = Vector2D.Distance(hitpos, targetLine.Start.Position); float distToEnd = Vector2D.Distance(hitpos, targetLine.End.Position); Vector2D offset = (distToStart < distToEnd ? targetLine.Start.Position : targetLine.End.Position).GetRotated(Angle2D.DegToRad(sourceAngle)); if (alignx) { if (Texture != null && Texture.IsImageLoaded) { offset.x %= Texture.Width / scaleX; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xpanningfloor" : "xpanningceiling"), (float)Math.Round(-offset.x), 0f); } if (aligny) { if (Texture != null && Texture.IsImageLoaded) { offset.y %= Texture.Height / scaleY; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "ypanningfloor" : "ypanningceiling"), (float)Math.Round(offset.y), 0f); } //update geometry Sector.UpdateSectorGeometry(false); }