/// <summary> /// Prep work before screen is painted /// </summary> /// <param name="gd"></param> /// <param name="state"></param> public void PreDraw(GraphicsDevice gd, WorldState state) { var pxOffset = -state.WorldSpace.GetScreenOffset(); 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 redrawStaticObjects = false; var redrawFloor = false; var redrawWall = false; var recacheWalls = false; var recacheFloors = false; var recacheTerrain = false; var recacheObjects = false; if (TicksSinceLight++ > 60 * 4) { damage.Add(new BlueprintDamage(BlueprintDamageType.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)) { redrawFloor = true; redrawWall = true; redrawStaticObjects = true; } break; case BlueprintDamageType.LIGHTING_CHANGED: redrawFloor = true; redrawWall = true; redrawStaticObjects = true; Blueprint.GenerateRoomLights(); state.OutsideColor = Blueprint.RoomColors[1]; state._3D.RoomLights = Blueprint.RoomColors; state._2D.AmbientLight.SetData(Blueprint.RoomColors); 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: recacheWalls = true; break; case BlueprintDamageType.ROOF_STYLE_CHANGED: Blueprint.RoofComp.StyleDirty = 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) { redrawWall = true; } if (recacheObjects) { redrawStaticObjects = true; } } damage.Clear(); var tileOffset = state.WorldSpace.GetTileFromScreen(-pxOffset); //scroll buffer loads in increments of SCROLL_BUFFER var newOff = GetScrollIncrement(pxOffset); var oldCenter = state.CenterTile; state.CenterTile += state.WorldSpace.GetTileFromScreen(newOff - pxOffset); //offset the scroll to the position of the scroll buffer. tileOffset = state.CenterTile; pxOffset = newOff; if (recacheTerrain) { Blueprint.Terrain.RegenTerrain(gd, state, Blueprint); } if (recacheWalls) { _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); _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); ClearDrawBuffer(StaticFloorCache); _2d.End(StaticFloorCache, true); } if (redrawFloor) { /** Draw archetecture to a texture **/ Promise <Texture2D> bufferTexture = null; Promise <Texture2D> depthTexture = null; using (var buffer = state._2D.WithBuffer(BUFFER_FLOOR_PIXEL, ref bufferTexture, BUFFER_FLOOR_DEPTH, ref depthTexture)) { _2d.SetScroll(pxOffset); while (buffer.NextPass()) { _2d.RenderCache(StaticFloorCache); Blueprint.Terrain.DepthMode = _2d.OutputDepth; Blueprint.Terrain.Draw(gd, state); } } StaticFloor = new ScrollBuffer(bufferTexture.Get(), depthTexture.Get(), pxOffset, new Vector3(tileOffset, 0)); } if (redrawWall) { Promise <Texture2D> bufferTexture = null; Promise <Texture2D> depthTexture = null; using (var buffer = state._2D.WithBuffer(BUFFER_WALL_PIXEL, ref bufferTexture, BUFFER_WALL_DEPTH, ref depthTexture)) { _2d.SetScroll(pxOffset); while (buffer.NextPass()) { _2d.RenderCache(StaticWallCache); } } StaticWall = new ScrollBuffer(bufferTexture.Get(), depthTexture.Get(), pxOffset, new Vector3(tileOffset, 0)); } 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 (redrawStaticObjects) { /** Draw static objects to a texture **/ Promise <Texture2D> bufferTexture = null; Promise <Texture2D> depthTexture = null; using (var buffer = state._2D.WithBuffer(BUFFER_STATIC_OBJECTS_PIXEL, ref bufferTexture, BUFFER_STATIC_OBJECTS_DEPTH, ref depthTexture)) { _2d.SetScroll(pxOffset); while (buffer.NextPass()) { _2d.RenderCache(StaticObjectsCache); } } StaticObjects = new ScrollBuffer(bufferTexture.Get(), depthTexture.Get(), pxOffset, new Vector3(tileOffset, 0)); } state.CenterTile = oldCenter; //revert to our real scroll position }