private IEnumerator DoRendering(bool forceRenderFullMap = false) { yield return(new WaitForFixedUpdate()); if (Rendering) { Log.Error("Progress Renderer is still rendering an image while a new rendering was requested. This can lead to missing or wrong data. (This can also happen in rare situations when you trigger manual rendering the exact same time as an automatic rendering happens. If you did that, just check your export folder if both renderings were done corrently and ignore this error.)"); } Rendering = true; // Temporary switch to this map for rendering bool switchedMap = false; Map rememberedMap = Find.CurrentMap; if (map != rememberedMap) { switchedMap = true; Current.Game.CurrentMap = map; } // Close world view if needed bool rememberedWorldRendered = WorldRendererUtility.WorldRenderedNow; if (rememberedWorldRendered) { CameraJumper.TryHideWorld(); } // Calculate rendered area float startX = 0; float startZ = 0; float endX = map.Size.x; float endZ = map.Size.z; if (!forceRenderFullMap) { List <Designation> cornerMarkers = map.designationManager.allDesignations.FindAll(des => des.def == DesignationDefOf.CornerMarker); if (cornerMarkers.Count > 1) { startX = endX; startZ = endZ; endX = 0; endZ = 0; foreach (Designation des in cornerMarkers) { IntVec3 cell = des.target.Cell; if (cell.x < startX) { startX = cell.x; } if (cell.z < startZ) { startZ = cell.z; } if (cell.x > endX) { endX = cell.x; } if (cell.z > endZ) { endZ = cell.z; } } endX += 1; endZ += 1; } } // Only use smoothing when rendering was not triggered manually if (!manuallyTriggered) { // Test if target render area changed to reset smoothing if (rsTargetStartX != startX || rsTargetStartZ != startZ || rsTargetEndX != endX || rsTargetEndZ != endZ) { // Check if area was manually reset or uninitialized (-1) to not smooth if (rsTargetStartX == -1f && rsTargetStartZ == -1f && rsTargetEndX == -1f && rsTargetEndZ == -1f) { rsCurrentPosition = 1f; } else { rsCurrentPosition = 1f / (PRModSettings.smoothRenderAreaSteps + 1); } rsOldStartX = rsTargetStartX; rsOldStartZ = rsTargetStartZ; rsOldEndX = rsTargetEndX; rsOldEndZ = rsTargetEndZ; rsTargetStartX = startX; rsTargetStartZ = startZ; rsTargetEndX = endX; rsTargetEndZ = endZ; } // Apply smoothing to render area if (rsCurrentPosition < 1f) { startX = rsOldStartX + (rsTargetStartX - rsOldStartX) * rsCurrentPosition; startZ = rsOldStartZ + (rsTargetStartZ - rsOldStartZ) * rsCurrentPosition; endX = rsOldEndX + (rsTargetEndX - rsOldEndX) * rsCurrentPosition; endZ = rsOldEndZ + (rsTargetEndZ - rsOldEndZ) * rsCurrentPosition; rsCurrentPosition += 1f / (PRModSettings.smoothRenderAreaSteps + 1); } } float distX = endX - startX; float distZ = endZ - startZ; // Calculate basic values that are used for rendering int imageWidth; int imageHeight; if (PRModSettings.scaleOutputImage) { imageHeight = PRModSettings.outputImageFixedHeight; imageWidth = (int)((float)imageHeight / distZ * distX); } else { imageWidth = (int)(distX * PRModSettings.pixelPerCell); imageHeight = (int)(distZ * PRModSettings.pixelPerCell); } int renderCountX = (int)Math.Ceiling((float)imageWidth / RenderTextureSize); int renderCountZ = (int)Math.Ceiling((float)imageHeight / RenderTextureSize); int renderWidth = (int)Math.Ceiling((float)imageWidth / renderCountX); int renderHeight = (int)Math.Ceiling((float)imageHeight / renderCountZ); float cameraPosX = (float)distX / 2 / renderCountX; float cameraPosZ = (float)distZ / 2 / renderCountZ; float orthographicSize = Math.Min(cameraPosX, cameraPosZ); orthographicSize = cameraPosZ; Vector3 cameraBasePos = new Vector3(cameraPosX, 15f + (orthographicSize - 11f) / 49f * 50f, cameraPosZ); RenderTexture renderTexture = RenderTexture.GetTemporary(renderWidth, renderHeight, 24); imageTexture = new Texture2D(imageWidth, imageHeight, TextureFormat.RGB24, false); Camera camera = Find.Camera; CameraDriver camDriver = camera.GetComponent <CameraDriver>(); camDriver.enabled = false; // Store current camera data Vector3 rememberedRootPos = map.rememberedCameraPos.rootPos; float rememberedRootSize = map.rememberedCameraPos.rootSize; float rememberedFarClipPlane = camera.farClipPlane; // Overwrite current view rect in the camera driver CellRect camViewRect = camDriver.CurrentViewRect; int camRectMinX = Math.Min((int)startX, camViewRect.minX); int camRectMinZ = Math.Min((int)startZ, camViewRect.minZ); int camRectMaxX = Math.Max((int)Math.Ceiling(endX), camViewRect.maxX); int camRectMaxZ = Math.Max((int)Math.Ceiling(endZ), camViewRect.maxZ); Traverse camDriverTraverse = Traverse.Create(camDriver); camDriverTraverse.Field("lastViewRect").SetValue(CellRect.FromLimits(camRectMinX, camRectMinZ, camRectMaxX, camRectMaxZ)); camDriverTraverse.Field("lastViewRectGetFrame").SetValue(Time.frameCount); yield return(new WaitForEndOfFrame()); // Set camera values needed for rendering camera.orthographicSize = orthographicSize; camera.farClipPlane = cameraBasePos.y + 6.5f; // Create a temporary camera for rendering /*Camera tmpCam = Camera.Instantiate(camera); * tmpCam.orthographicSize = orthographicSize; * tmpCam.farClipPlane = cameraPos.y + 6.5f;*/ // Set render textures //tmpCam.targetTexture = renderTexture; camera.targetTexture = renderTexture; RenderTexture.active = renderTexture; // Render the image texture try { if (PRModSettings.renderWeather) { map.weatherManager.DrawAllWeather(); } for (int i = 0; i < renderCountZ; i++) { for (int j = 0; j < renderCountX; j++) { camera.transform.position = new Vector3(startX + cameraBasePos.x * (2 * j + 1), cameraBasePos.y, startZ + cameraBasePos.z * (2 * i + 1)); camera.Render(); imageTexture.ReadPixels(new Rect(0, 0, renderWidth, renderHeight), renderWidth * j, renderHeight * i, false); } } } catch (Exception e) { Log.Error(e.Message, true); } // Restore camera and viewport RenderTexture.active = null; //tmpCam.targetTexture = null; camera.targetTexture = null; camera.farClipPlane = rememberedFarClipPlane; camDriver.SetRootPosAndSize(rememberedRootPos, rememberedRootSize); camDriver.enabled = true; RenderTexture.ReleaseTemporary(renderTexture); // Switch back to world view if needed if (rememberedWorldRendered) { CameraJumper.TryShowWorld(); } // Switch back to remembered map if needed if (switchedMap) { Current.Game.CurrentMap = rememberedMap; } // Sinal finished rendering Rendering = false; yield return(null); // Start encoding DoEncoding(); yield break; }