/// <summary> /// Reserves a rectangular area for the given image in this.Maze. /// The chosen location is remembered in this.imageLocations. /// Returns true if the reservation was successful. /// </summary> /// <param name="contourImage"></param> /// <returns></returns> private bool AddImage(ContourImage contourImage) { Image img = contourImage.DisplayedImage; int padding = MazePainter.ApplyScaleFactor(8) + this.wallWidth; int sqW = (img.Width + padding) / this.gridWidth + 1; int sqH = (img.Height + padding) / this.gridWidth + 1; int xOffsetImg = (sqW * gridWidth - img.Width) / 2; int yOffsetImg = (sqH * gridWidth - img.Height) / 2; OutlineShape shape = (ContourImage.DisplayProcessedImage ? contourImage.GetCoveredShape(gridWidth, wallWidth, xOffsetImg, yOffsetImg) : null); Rectangle rect; if (Maze.ReserveRectangle(sqW, sqH, 2, shape, out rect)) { // Remember the image data and location. It will be painted in PaintMaze(). int x = rect.X * gridWidth + xOffset + xOffsetImg; int y = rect.Y * gridWidth + yOffset + yOffsetImg; imageLocations.Add(new Rectangle(x, y, img.Width, img.Height)); return(true); } else { return(false); } }
public void Setup() { if (painter.HasBufferAlternate) { // the Setup() method was already executed for creating the alternate buffer this.Invalidate(); return; } if (settingsData != null) { this.TakeParametersFrom(settingsData); return; } #region Set up the painter. painter.Setup(); MazePainter.SuggestWidths(painter.GridWidth, painter.VisibleWalls, out int squareWidth, out int pathWidth, out int wallWidth); this.Setup(squareWidth, wallWidth, pathWidth); #endregion }
/// <summary> /// Constructor. /// Creates and starts an AriadneController. /// </summary> /// <param name="windowHandleArg"></param> private ScreenSaverPreviewController(string windowHandleArg) { // Get the window in which we are supposed to paint. this.parentHwnd = (IntPtr)UInt32.Parse(windowHandleArg); this.targetRectangle = Platform.GetClientRectangle(parentHwnd); //Log.WriteLine("targetRectangle = " + targetRectangle); // Create a MazePainter. this.targetGraphics = Graphics.FromHwnd(parentHwnd); this.painter = new MazePainter(targetGraphics, targetRectangle, this as IMazePainterClient, true); // Create and display the first maze. this.OnNew(null, null); // Create an AriadneController. SolverController controller = new SolverController(null, painter, null); this.ariadneController = new AriadneController(this, controller); ariadneController.RepeatMode = true; // Start the AriadneController. ariadneController.Start(); // Start a supervisor timer. CreateSupervisorTimer(); }
/// <summary> /// Constructor. /// </summary> public SolverController( IMazeForm mazeForm, MazePainter mazePainter, ProgressBar visitedProgressBar) { this.mazeForm = mazeForm; this.mazePainter = mazePainter; this.visitedProgressBar = visitedProgressBar; }
/// <summary> /// Will stop the AriadneController and de-construct this object. /// </summary> private void TargetWindowClosing(object sender, FormClosingEventArgs e) { // When the form is closed, stop the controller. ariadneController.Stop(); // Discard all member variables. this.ariadneController = null; this.painter = null; }
/// <summary> /// Reserves a region of the maze covered by the coveringControl. /// This MazeUserControl and the coveringControl must have the same Parent, i.e. a common coordinate system. /// </summary> /// <param name="coveringControl"></param> /// <exception cref="ArgumentException">The given Control has a differnent Parent.</exception> public bool ReserveArea(Control coveringControl) { if (coveringControl.Parent != this.Parent) { throw new ArgumentException("Must have the same Parent.", nameof(coveringControl)); } // Dimensions of the control in square coordinates. int x, y, w, h; x = XCoordinate(coveringControl.Left, true); y = YCoordinate(coveringControl.Top, true); w = 1 + XCoordinate(coveringControl.Right - 1, false) - x; h = 1 + YCoordinate(coveringControl.Bottom - 1, false) - y; int padding = wallWidth + MazePainter.ApplyScaleFactor(6); if (0 < x && x + w < Maze.XSize) { w = 1 + (coveringControl.Width + padding) / gridWidth; } if (0 < y && y + h < Maze.YSize) { h = 1 + (coveringControl.Height + padding) / gridWidth; } bool result = Maze.ReserveRectangle(x, y, w, h, null); // Move the control into the center of the reserved area. if (result) { int cx = coveringControl.Left; int cy = coveringControl.Top; if (0 < x && x + w < Maze.XSize) { cx = this.Location.X + xOffset + x * gridWidth; cx += 1 + (w * gridWidth - wallWidth - coveringControl.Width) / 2; } if (0 < y && y + h < Maze.YSize) { cy = this.Location.Y + yOffset + y * gridWidth; cy += 1 + (h * gridWidth - wallWidth - coveringControl.Height) / 2; } // Adjust the control's location coveringControl.Location = new Point(cx, cy); controlLocations.Add(coveringControl.Bounds); } return(result); }
/// <summary> /// Create controllers for our maze's embedded mazes. /// </summary> private void CreateEmbeddedSolvers() { this.mazePainter.ClearSharedPainters(); foreach (Maze embeddedMaze in Maze.EmbeddedMazes) { MazePainter embeddedPainter = this.mazePainter.CreateSharedPainter(embeddedMaze); embeddedPainter.BlinkingCounter = -1; EmbeddedSolverController embeddedController = new EmbeddedSolverController(this, embeddedPainter); this.embeddedControllers.Add(embeddedController); embeddedController.StartDelayRelativeDistance = 0.2 + 0.4 * Maze.Random.NextDouble(); } }
/// <summary> /// Creates a new maze. /// </summary> public void OnNew(object sender, EventArgs e) { #region Set up the painter. painter.Setup(); int squareWidth; int pathWidth; int wallWidth; MazePainter.SuggestWidths(painter.GridWidth, painter.VisibleWalls, out squareWidth, out pathWidth, out wallWidth); painter.Setup(squareWidth, wallWidth, pathWidth); #endregion painter.Reset(); painter.BlinkingCounter = 0; // Create and display a maze. painter.CreateMaze(null); painter.PaintMaze(null); }
/// <summary> /// Creates a ScreenSaverController instance, /// draws an initial maze /// and starts an AriadneController. /// </summary> /// <param name="windowHandleArg">The MazePainter will draw on this window.</param> /// <remarks> /// If this is not the primary screen, no cotroller is started, /// the application will terminate and the screen will stay blank. /// </remarks> public ScreenSaverController(string windowHandleArg) { #region Evaluate the given window's properties. var windowHandle = (IntPtr)UInt32.Parse(windowHandleArg); var targetGraphics = Graphics.FromHwnd(windowHandle); var targetRectangle = Platform.GetClientRectangle(windowHandle); //Log.WriteLine("targetRectangle = " + targetRectangle, true); // {X=0,Y=0,Width=1366,Height=768} #endregion #if true #region Blank secondary screen(s). // ... because more than one of these mazes is just too distracting. :-) if (!IsOnPrimaryScreen(windowHandle)) { // We don't have to do anything, really. // xscreensaver has given us a blank (black) window and we may // terminate the application //Log.WriteLine("Goodbye on " + targetRectangle, true); //Application.Run(); Application.Exit(); } #endregion #endif // Create an ImageLoader, now that it is clear that we will need it. Directory.ResultValidForSeconds = -1; var imageLoader = ImageLoader.GetScreenSaverImageLoader(Screen.PrimaryScreen.Bounds); #region Create a MazePainter. this.painter = new MazePainter(targetGraphics, targetRectangle, this as IMazePainterClient); #endregion #region Create a MazeUserControl. this.mazeUserControl = new MazeUserControl(painter, targetRectangle.Size); this.mazeUserControl.ImageLoader = imageLoader; this.mazeUserControl.MazeForm = this; #endregion #region Apply some registered options. if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_PAINT_ALL_WALLS) == false) { painter.RandomizeWallVisibility = true; } ContourImage.DisplayProcessedImage = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_IMAGE_SUBTRACT_BACKGROUND); // Load background images. if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_BACKGROUND_IMAGES)) { string imageFolder = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_BACKGROUND_IMAGE_FOLDER); if (imageFolder == "") { imageFolder = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_IMAGE_FOLDER); } int percentage = ((RegisteredOptions.GetIntSetting(RegisteredOptions.OPT_IMAGE_NUMBER) > 0) ? 20 : 100); painter.CreateBackgroundImageLoader(imageFolder, percentage); } if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_SHOW_DETAILS_BOX)) { this.infoPanelPainter = new InfoPanelPainter(painter); } #endregion // Create and display the first maze. this.OnNew(null, null); #region Create and start an AriadneController. SolverController controller = new SolverController(this, painter, null); this.ariadneController = new AriadneController(this, controller); ariadneController.RepeatMode = true; ariadneController.Start(); #endregion }
/// <summary> /// Create an object that provides useful functionality to a ScreenSaverController. /// Note: This object will not be displayed on any form. /// </summary> public MazeUserControl(MazePainter painter, Size size) { this.painter = painter; this.Location = new Point(0, 0); this.Size = size; }
public MazeUserControl() { InitializeComponent(); this.painter = new MazePainter(this.CreateGraphics(), this.DisplayRectangle, this as IMazePainterClient); }
/// <summary> /// Update the other controls to reflect the derived changes. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnDataChanged(object sender, EventArgs e) { // Avoid an infinite recursion if (_busyOnDataChanged) { return; } try { _busyOnDataChanged = true; #region Layout data if (data.AutoGridWidthModified) { if (!data.AutoGridWidth) { data.AutoSquareWidth = true; data.AutoPathWidth = true; data.AutoWallWidth = true; } } if (data.AutoSquareWidthModified || data.AutoPathWidthModified || data.AutoWallWidthModified) { if (!data.AutoSquareWidth || !data.AutoPathWidth || !data.AutoWallWidth) { data.AutoGridWidth = true; } } bool gridWithModifiedManually = data.GridWidthModified; if (data.GridWidthModified) { data.AutoGridWidth = false; int squareWidth, pathWidth, wallWidth; bool visibleWalls = (data.WallVisibility != AriadneSettingsData.WallVisibilityEnum.Never); MazePainter.SuggestWidths(data.GridWidth, visibleWalls, out squareWidth, out pathWidth, out wallWidth); data.WallWidth = wallWidth; data.SquareWidth = squareWidth; data.PathWidth = pathWidth; } if (data.PathWidthModified) { data.AutoPathWidth = gridWithModifiedManually; data.SquareWidth = Math.Max(data.PathWidth, data.SquareWidth); } if (data.SquareWidthModified) { data.AutoSquareWidth = gridWithModifiedManually; data.PathWidth = Math.Min(data.PathWidth, data.SquareWidth); data.GridWidth = Math.Min(data.SquareWidth + data.WallWidth, MazePainter.MaxGridWidth); data.WallWidth = data.GridWidth - data.SquareWidth; } if (data.WallWidthModified) { data.AutoWallWidth = gridWithModifiedManually; data.GridWidth = Math.Min(data.SquareWidth + data.WallWidth, MazePainter.MaxGridWidth); data.SquareWidth = data.GridWidth - data.WallWidth; } if (gridWithModifiedManually || (data.AutoGridWidthModified && !data.AutoGridWidth)) { data.AutoSquareWidth = true; data.AutoPathWidth = true; data.AutoWallWidth = true; } if (!data.AutoSquareWidth || !data.AutoPathWidth || !data.AutoWallWidth) { data.AutoGridWidth = true; } #endregion #region Shape data if (data.MazeWidthModified) { data.AutoMazeWidth = false; } if (data.MazeHeightModified) { data.AutoMazeHeight = false; } if (data.SeedModified) { data.AutoSeed = false; } #endregion CalculateResultingArea(); data.ClearModifedFlags(); dataBindingSource.ResetCurrentItem(); } finally { _busyOnDataChanged = false; } }
public InfoPanelPainter(MazePainter mazePainter) { this.mazePainter = mazePainter; #region Create Control objects outerInfoPanel = new Panel { Location = new Point(0, 0), // will be relocated later Size = new Size(444, 44), Padding = new Padding(3), BackColor = Control.DefaultBackColor, }; innerInfoPanel = new Panel { Location = new Point(3, 3), Size = new Size(438, 38), BorderStyle = BorderStyle.Fixed3D, Padding = new Padding(2), //BackColor = Color.Beige, }; infoLabelCaption = new Label { Location = new Point(2, 1), Size = new Size(430, 16), Padding = new Padding(0), Text = "Caption", TextAlign = ContentAlignment.MiddleCenter, }; infoLabelStatus = new Label { Location = new Point(2, 17), Size = new Size(430, 16), Padding = new Padding(0), Text = "Status", TextAlign = ContentAlignment.MiddleCenter, }; outerInfoPanel.Controls.Add(innerInfoPanel); innerInfoPanel.Controls.Add(infoLabelCaption); innerInfoPanel.Controls.Add(infoLabelStatus); innerInfoPanel.ResumeLayout(false); outerInfoPanel.ResumeLayout(true); #endregion #region Create a bitmap for rendering the Controls //targetGraphics = graphics; bitmap = new Bitmap(outerInfoPanel.Size.Width, outerInfoPanel.Size.Height); bitmapGraphics = Graphics.FromImage(bitmap); // Approximate a standard label's settings bitmapGraphics.SmoothingMode = SmoothingMode.AntiAlias; bitmapGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic; bitmapGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality; bitmapGraphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; #endregion Paint(); }