/// <summary> /// Pre-Draw /// </summary> /// <param name="device"></param> public override void PreDraw(GraphicsDevice device) { base.PreDraw(device); if (HasInit == false) { return; } BoundView(); State._2D.PreciseZoom = State.PreciseZoom; State.OutsideColor = Blueprint.OutsideColor; FSO.Common.Rendering.Framework.GameScreen.ClearColor = new Color(new Color(0x72, 0x72, 0x72).ToVector4() * State.OutsideColor.ToVector4()); foreach (var sub in Blueprint.SubWorlds) { sub.PreDraw(device, State); } State.UpdateInterpolation(); if (Blueprint != null) { foreach (var ent in Blueprint.Objects) { ent.Update(null, State); } } //For all the tiles in the dirty list, re-render them //PPXDepthEngine.SetPPXTarget(null, null, true); State.PrepareLighting(); State._2D.Begin(this.State.Camera); _2DWorld.PreDraw(device, State); device.SetRenderTarget(null); State._2D.End(); State._3D.Begin(device); _3DWorld.PreDraw(device, State); State._3D.End(); if (UseBackbuffer) { PPXDepthEngine.SetPPXTarget(null, null, true); InternalDraw(device); device.SetRenderTarget(null); } return; }
/// <summary> /// Pre-Draw /// </summary> /// <param name="device"></param> public override void PreDraw(GraphicsDevice device) { //bound the scroll so we can't see gray space. float boundfactor = 0.5f; switch (State.Zoom) { case WorldZoom.Near: boundfactor = 1.20f; break; case WorldZoom.Medium: boundfactor = 1.05f; break; } boundfactor *= Blueprint?.Width ?? 64; var off = 0.5f * (Blueprint?.Width ?? 64); var tile = State.CenterTile; tile = new Vector2(Math.Min(boundfactor + off, Math.Max(off - boundfactor, tile.X)), Math.Min(boundfactor + off, Math.Max(off - boundfactor, tile.Y))); if (tile != State.CenterTile) { State.CenterTile = tile; } base.PreDraw(device); if (HasInit == false) { return; } State._2D.PreciseZoom = State.PreciseZoom; State.OutsideColor = Blueprint.OutsideColor; foreach (var sub in Blueprint.SubWorlds) { sub.PreDraw(device, State); } if (Blueprint != null) { foreach (var ent in Blueprint.Objects) { ent.Update(null, State); } } //For all the tiles in the dirty list, re-render them //PPXDepthEngine.SetPPXTarget(null, null, true); State.PrepareLighting(); State._2D.Begin(this.State.Camera); _2DWorld.PreDraw(device, State); device.SetRenderTarget(null); State._2D.End(); State._3D.Begin(device); _3DWorld.PreDraw(device, State); State._3D.End(); if (UseBackbuffer) { PPXDepthEngine.SetPPXTarget(null, null, true); InternalDraw(device); device.SetRenderTarget(null); } return; }
/// <summary> /// Prep work before screen is painted /// </summary> /// <param name="gd"></param> /// <param name="state"></param> public virtual void PreDraw(GraphicsDevice gd, WorldState state) { //var oht = state.BaseHeight; //state.BaseHeight = 0; var pxOffset = -state.WorldSpace.GetScreenOffset(); //state.BaseHeight = oht; var damage = Blueprint.Damage; var _2d = state._2D; /** * Tasks: * If zoom or rotation has changed, redraw all static layers * If scroll has changed, redraw static layer if the scroll is outwith the buffered region * If architecture has changed, redraw appropriate static layer * If there is a new object in the static layer, redraw the static layer * If an objects in the static layer has changed, redraw the static layer and move the object to the dynamic layer * If wall visibility has changed, redraw wall layer (should think about how this works with breakthrough wall mode */ var im = state.ThisFrameImmediate; var redrawStaticObjects = im; var redrawFloor = im; var redrawWall = im; var recacheWalls = false; var recacheCutaway = false; var recacheFloors = false; var recacheTerrain = false; var recacheObjects = false; var drawImmediate = false; var lightChangeType = 0; if (TicksSinceLight++ > 60 * 4) { damage.Add(new BlueprintDamage(BlueprintDamageType.OUTDOORS_LIGHTING_CHANGED)); } WorldObjectRenderInfo info = null; foreach (var item in damage) { switch (item.Type) { case BlueprintDamageType.ROTATE: case BlueprintDamageType.ZOOM: case BlueprintDamageType.LEVEL_CHANGED: recacheObjects = true; recacheWalls = true; recacheFloors = true; //recacheTerrain = true; break; case BlueprintDamageType.SCROLL: if (StaticObjects == null || StaticObjects.PxOffset != GetScrollIncrement(pxOffset, state)) { redrawFloor = true; redrawWall = true; redrawStaticObjects = true; } break; case BlueprintDamageType.PRECISE_ZOOM: drawImmediate = true; redrawFloor = redrawWall = redrawStaticObjects = true; break; case BlueprintDamageType.LIGHTING_CHANGED: if (lightChangeType >= 2) { break; } var room = (ushort)item.TileX; redrawFloor = true; redrawWall = true; redrawStaticObjects = true; state.Light?.InvalidateRoom(room); Blueprint.GenerateRoomLights(); state.OutsideColor = Blueprint.RoomColors[1]; state._3D.RoomLights = Blueprint.RoomColors; state.OutsidePx.SetData(new Color[] { new Color(Blueprint.OutsideColor, (Blueprint.OutsideColor.R + Blueprint.OutsideColor.G + Blueprint.OutsideColor.B) / (255 * 3f)) }); if (state.AmbientLight != null) { state.AmbientLight.SetData(Blueprint.RoomColors); } TicksSinceLight = 0; break; case BlueprintDamageType.OUTDOORS_LIGHTING_CHANGED: if (lightChangeType >= 1) { break; } lightChangeType = 1; redrawFloor = true; redrawWall = true; redrawStaticObjects = true; Blueprint.GenerateRoomLights(); state.OutsideColor = Blueprint.RoomColors[1]; state._3D.RoomLights = Blueprint.RoomColors; state.OutsidePx.SetData(new Color[] { new Color(Blueprint.OutsideColor, (Blueprint.OutsideColor.R + Blueprint.OutsideColor.G + Blueprint.OutsideColor.B) / (255 * 3f)) }); if (state.AmbientLight != null) { state.AmbientLight.SetData(Blueprint.RoomColors); } state.Light?.InvalidateOutdoors(); TicksSinceLight = 0; break; case BlueprintDamageType.OBJECT_MOVE: /** Redraw if its in static layer **/ info = GetRenderInfo(item.Component); if (info.Layer == WorldObjectRenderLayer.STATIC) { recacheObjects = true; info.Layer = WorldObjectRenderLayer.DYNAMIC; } if (item.Component is ObjectComponent) { ((ObjectComponent)item.Component).DynamicCounter = 0; } break; case BlueprintDamageType.OBJECT_GRAPHIC_CHANGE: /** Redraw if its in static layer **/ info = GetRenderInfo(item.Component); if (info.Layer == WorldObjectRenderLayer.STATIC) { recacheObjects = true; info.Layer = WorldObjectRenderLayer.DYNAMIC; } if (item.Component is ObjectComponent) { ((ObjectComponent)item.Component).DynamicCounter = 0; } break; case BlueprintDamageType.OBJECT_RETURN_TO_STATIC: info = GetRenderInfo(item.Component); if (info.Layer == WorldObjectRenderLayer.DYNAMIC) { recacheObjects = true; info.Layer = WorldObjectRenderLayer.STATIC; } break; case BlueprintDamageType.WALL_CUT_CHANGED: recacheCutaway = true; break; case BlueprintDamageType.ROOF_STYLE_CHANGED: Blueprint.RoofComp.StyleDirty = true; break; case BlueprintDamageType.ROOM_CHANGED: for (sbyte i = 0; i < Blueprint.RoomMap.Length; i++) { state.Rooms.SetRoomMap(i, Blueprint.RoomMap[i]); } if (state.Light != null) { if (lightChangeType < 2) { lightChangeType = 2; state.Light.InvalidateAll(); } } Blueprint.RoofComp.ShapeDirty = true; break; case BlueprintDamageType.FLOOR_CHANGED: case BlueprintDamageType.WALL_CHANGED: //recacheTerrain = true; recacheFloors = true; recacheWalls = true; Blueprint.RoofComp.ShapeDirty = true; break; } } if (recacheFloors || recacheTerrain) { redrawFloor = true; } if (recacheWalls || recacheCutaway) { redrawWall = true; } if (recacheObjects) { redrawStaticObjects = true; } damage.Clear(); //scroll buffer loads in increments of SCROLL_BUFFER var newOff = GetScrollIncrement(pxOffset, state); var oldCenter = state.CenterTile; state.CenterTile += state.WorldSpace.GetTileFromScreen(newOff - pxOffset); //offset the scroll to the position of the scroll buffer. var tileOffset = state.CenterTile; pxOffset = newOff; if (recacheTerrain) { Blueprint.Terrain.RegenTerrain(gd, state, Blueprint); } if (recacheWalls) { Blueprint.WCRC?.Generate(gd, state, false); } else if (recacheCutaway) { Blueprint.WCRC?.Generate(gd, state, true); } state.Light?.ParseInvalidated((sbyte)(state.Level + ((state.DrawRoofs) ? 1 : 0)), state); if (recacheWalls || recacheCutaway) { _2d.Pause(); _2d.Resume(); //clear the sprite buffer before we begin drawing what we're going to cache Blueprint.WallComp.Draw(gd, state); ClearDrawBuffer(StaticWallCache); state.PrepareLighting(); _2d.End(StaticWallCache, true); } if (recacheFloors) { _2d.Pause(); _2d.Resume(); //clear the sprite buffer before we begin drawing what we're going to cache //Blueprint.FloorComp.Draw(gd, state); Blueprint.FloorGeom.FullReset(gd, state.BuildMode > 1); ClearDrawBuffer(StaticFloorCache); _2d.End(StaticFloorCache, true); } if (recacheObjects) { _2d.Pause(); _2d.Resume(); foreach (var obj in Blueprint.Objects) { if (obj.Level > state.Level) { continue; } var renderInfo = GetRenderInfo(obj); if (renderInfo.Layer == WorldObjectRenderLayer.STATIC) { var tilePosition = obj.Position; _2d.OffsetPixel(state.WorldSpace.GetScreenFromTile(tilePosition)); _2d.OffsetTile(tilePosition); _2d.SetObjID(obj.ObjectID); obj.Draw(gd, state); } } ClearDrawBuffer(StaticObjectsCache); _2d.End(StaticObjectsCache, true); } if (!drawImmediate) { state.PrepareLighting(); if (redrawStaticObjects || redrawFloor || redrawWall) { /** Draw static objects to a texture **/ Promise <Texture2D> bufferTexture = null; Promise <Texture2D> depthTexture = null; using (var buffer = state._2D.WithBuffer(BUFFER_STATIC, ref bufferTexture, BUFFER_STATIC_DEPTH, ref depthTexture)) { while (buffer.NextPass()) { DrawFloorBuf(gd, state, pxOffset); DrawWallBuf(gd, state, pxOffset); DrawObjBuf(gd, state, pxOffset); } } StaticObjects = new ScrollBuffer(bufferTexture.Get(), depthTexture.Get(), newOff, new Vector3(tileOffset, 0)); } } //state._2D.PreciseZoom = state.PreciseZoom; state.CenterTile = oldCenter; //revert to our real scroll position state.ThisFrameImmediate = drawImmediate; }