text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FlatRedBall.IO;
using FlatRedBall.Glue.CodeGeneration.CodeBuilder;
using FlatRedBall.Glue.Parsing;
using FlatRedBall.Utilities;
using FlatRedBall.Glue.Plugins.ExportedImplementations;
using FlatRedBall.Glue.SaveClasses;
using System.Globalization;
using FlatRedBall.Glue.Plugins.EmbeddedPlugins.CameraPlugin;
using FlatRedBall.Glue.IO;
using FlatRedBall.Glue.Managers;
using Microsoft.Xna.Framework.Graphics;
using static FlatRedBall.Glue.SaveClasses.GlueProjectSave;

namespace FlatRedBall.Glue.CodeGeneration
{
    internal class CameraSetupCodeGenerator
    {
        #region Game1 Related code

        public static void GenerateCallInGame1(string gameFileName, bool whetherToCall)
        {
            var hasCameraCodeInGeneratedCode =
                 GlueState.Self.CurrentGlueProject.FileVersion >= (int)GlueProjectSave.GluxVersions.StartupInGeneratedGame;

            if (hasCameraCodeInGeneratedCode)
            {
                GlueCommands.Self.GenerateCodeCommands.GenerateGame1();
            }
            else
            {
                GenerateCameraSetupInGame1(gameFileName, whetherToCall);
            }
        }

        private static void GenerateCameraSetupInGame1(string gameFileName, bool whetherToCall)
        {
            string contents = null;
            if (!string.IsNullOrEmpty(gameFileName))
            {

                GlueCommands.Self.TryMultipleTimes(() =>
                    contents = FileManager.FromFileText(GlueState.Self.CurrentGlueProjectDirectory + gameFileName));
            }

            if (!string.IsNullOrEmpty(contents))
            {

                string whatToLookFor = "CameraSetup.SetupCamera(SpriteManager.Camera, graphics";

                string lineToReplaceWith = "CameraSetup.SetupCamera(SpriteManager.Camera, graphics);";

                if (whetherToCall)
                {
                    lineToReplaceWith = "\t\t\t" + lineToReplaceWith;
                }
                else
                {
                    lineToReplaceWith = "\t\t\t//" + lineToReplaceWith;
                }

                if (contents.Contains(whatToLookFor))
                {
                    // Only replace this if it's commented out:
                    int startOfLine;
                    int endOfLine;
                    StringFunctions.GetStartAndEndOfLineContaining(contents, "CameraSetup.SetupCamera", out startOfLine, out endOfLine);

                    string line = contents.Substring(startOfLine, endOfLine - startOfLine);

                    bool shouldReplace = line.Trim().StartsWith("//");
                    if (shouldReplace)
                    {
                        StringFunctions.ReplaceLine(ref contents, "CameraSetup.SetupCamera", lineToReplaceWith);
                    }
                }
                else
                {
                    // We gotta find where to put the start call.  This should be after
                    // FlatRedBallServices.InitializeFlatRedBall

                    int index = CodeParser.GetIndexAfterBaseInitialize(contents);

                    if (index == -1)
                    {
                        GlueCommands.Self.PrintError("Could not find code in Game1.cs to add camera setup");
                    }
                    else
                    {
                        contents = contents.Insert(index, lineToReplaceWith + Environment.NewLine);
                    }

                }

                // load to see if it's changed, and only change it if so:
                var absoluteFile = new FilePath(FileManager.RelativeDirectory + gameFileName);

                var shouldSave = absoluteFile.Exists() == false;

                if (!shouldSave)
                {
                    var existingText = FileManager.FromFileText(absoluteFile.FullPath);
                    shouldSave = existingText != contents;
                }

                if (shouldSave)
                {
                    GlueCommands.Self.TryMultipleTimes(() =>
                    {
                        FileManager.SaveText(contents, absoluteFile.FullPath);
                    }, 5);
                }
            }
        }

        #endregion

        public static void UpdateOrAddCameraSetup()
        {
            TaskManager.Self.AddOrRunIfTasked(() =>
            {
                FilePath fileName;

                if(GlueState.Self.CurrentGlueProject.FileVersion >= (int)GluxVersions.GeneratedCameraSetupFile)
                {
                    fileName = GlueState.Self.CurrentGlueProjectDirectory + @"Setup\CameraSetup.Generated.cs";
                }
                else
                {
                    fileName = GlueState.Self.CurrentGlueProjectDirectory + @"Setup\CameraSetup.cs";
                }

                string newContents = GetCameraSetupCsContents();

                GlueCommands.Self.TryMultipleTimes(() => FileManager.SaveText(newContents, fileName.FullPath), 5);

                // Now, verify that this thing is part of the project.
                bool wasAdded = GlueCommands.Self.ProjectCommands.UpdateFileMembershipInProject(ProjectManager.ProjectBase, fileName, false, false);

                if (wasAdded)
                {
                    GlueCommands.Self.ProjectCommands.SaveProjects();
                }

            }, "Generating camera setup code", TaskExecutionPreference.AddOrMoveToEnd);
        }

        private static string GetCameraSetupCsContents()
        {
            bool shouldGenerateNew = GlueState.Self.CurrentGlueProject.DisplaySettings != null;

            string fileContents = null;

            ICodeBlock classContents = new CodeBlockBase(null);

            classContents.Line("// This is a generated file created by Glue. To change this file, edit the camera settings in Glue.");
            classContents.Line("// To access the camera settings, push the camera icon.");
            if(shouldGenerateNew == false)
            {
                classContents.TabCount = 2;
                fileContents = GetDisplaySetupOld(classContents);
            }
            else
            {
                fileContents = GetDisplaySetupNew(classContents);
            }
            return fileContents;
        }

        private static string GetDisplaySetupNew(ICodeBlock fileCode)
        {
            var displaySettings = GlueState.Self.CurrentGlueProject.DisplaySettings;

            fileCode.Line("using Camera = FlatRedBall.Camera;");

            var namespaceContents = fileCode.Namespace(ProjectManager.ProjectNamespace);

            GenerateCameraSetupDataClass(namespaceContents);

            GenerateResizeBehaviorEnum(namespaceContents);

            GenerateWidthOrHeightEnum(namespaceContents);

            var classContents = namespaceContents.Class("internal static", "CameraSetup");

            classContents.Line("static Microsoft.Xna.Framework.GraphicsDeviceManager graphicsDeviceManager;");

            GenerateStaticCameraSetupDefaults(classContents);

            GenerateResetMethodNew(displaySettings.GenerateDisplayCode, classContents);

            GenerateSetupCameraMethodNew(displaySettings.GenerateDisplayCode, classContents);

            GenerateResetWindow(displaySettings.GenerateDisplayCode, classContents);

            GenerateHandleResize(classContents);

            if(GetIfHasGumProject())
            {
                GenerateSetGumResolutionValues(classContents);
            }

            GenerateSetAspectRatio(classContents);

            GenerateKeepWindowOnTopCode(classContents);

            return fileCode.ToString();
        }

        private static void GenerateSetGumResolutionValues(ICodeBlock codeblock)
        {
            var functionBlock = codeblock.Function("public static void", "ResetGumResolutionValues", "");
            var gumIfBlock = functionBlock.If("Data.ResizeBehaviorGum == ResizeBehavior.IncreaseVisibleArea");

            //gumIfBlock.Line("Gum.Wireframe.GraphicalUiElement.CanvasHeight = FlatRedBall.Camera.Main.DestinationRectangle.Height / (Data.Scale / 100.0f);");
            //gumIfBlock.Line("Gum.Wireframe.GraphicalUiElement.CanvasWidth = FlatRedBall.Camera.Main.DestinationRectangle.Width / (Data.Scale / 100.0f);");
            gumIfBlock.Line("global::RenderingLibrary.SystemManagers.Default.Renderer.Camera.Zoom = Data.Scale/100.0f;");
            gumIfBlock.Line("Gum.Wireframe.GraphicalUiElement.CanvasWidth = Gum.Managers.ObjectFinder.Self.GumProjectSave.DefaultCanvasWidth;");
            gumIfBlock.Line("Gum.Wireframe.GraphicalUiElement.CanvasHeight = Gum.Managers.ObjectFinder.Self.GumProjectSave.DefaultCanvasHeight; ");

            var gumElseBlock = gumIfBlock.End().Else();

            gumElseBlock.Line("Gum.Wireframe.GraphicalUiElement.CanvasHeight = Data.ResolutionHeight / (Data.ScaleGum/100.0f);");
            var gumAspectRatio = gumElseBlock.If("Data.EffectiveAspectRatio != null")
                .Line(@"

                    if(Data.DominantInternalCoordinates == WidthOrHeight.Height)
                    {
                        Gum.Wireframe.GraphicalUiElement.CanvasHeight = Data.ResolutionHeight / (Data.ScaleGum / 100.0f);
                        Gum.Wireframe.GraphicalUiElement.CanvasWidth = FlatRedBall.Math.MathFunctions.RoundToInt((decimal)Gum.Wireframe.GraphicalUiElement.CanvasHeight * Data.EffectiveAspectRatio.Value);
                    }
                    else
                    {
                        Gum.Wireframe.GraphicalUiElement.CanvasWidth = Data.ResolutionWidth / (Data.ScaleGum/100.0f);
                        Gum.Wireframe.GraphicalUiElement.CanvasHeight = FlatRedBall.Math.MathFunctions.RoundToInt((decimal)Gum.Wireframe.GraphicalUiElement.CanvasHeight / Data.EffectiveAspectRatio.Value);
                    }

                    var resolutionAspectRatio = FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionWidth / (decimal)FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionHeight;
                    int destinationRectangleWidth;
                    int destinationRectangleHeight;
                    int x = 0;
                    int y = 0;
                    if (Data.EffectiveAspectRatio.Value > resolutionAspectRatio)
                    {
                        destinationRectangleWidth = FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionWidth;
                        destinationRectangleHeight = FlatRedBall.Math.MathFunctions.RoundToInt(destinationRectangleWidth / (float)Data.EffectiveAspectRatio.Value);
                    }
                    else
                    {
                        destinationRectangleHeight = FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionHeight;
                        destinationRectangleWidth = FlatRedBall.Math.MathFunctions.RoundToInt(destinationRectangleHeight * (float)Data.EffectiveAspectRatio.Value);
                    }

                    var canvasHeight = Gum.Wireframe.GraphicalUiElement.CanvasHeight;
                    var zoom = (float)destinationRectangleHeight / (float)Gum.Wireframe.GraphicalUiElement.CanvasHeight;
                    if(global::RenderingLibrary.SystemManagers.Default != null)
                    {
                        global::RenderingLibrary.SystemManagers.Default.Renderer.Camera.Zoom = zoom;

                        foreach(var layer in global::RenderingLibrary.SystemManagers.Default.Renderer.Layers)
                        {
                            if(layer.LayerCameraSettings != null)
                            {
                                layer.LayerCameraSettings.Zoom = zoom;
                            }
                        }
                    }

")
                .End().Else()
                .Line(@"

                    // since a fixed aspect ratio isn't specified, adjust the width according to the
                    // current game aspect ratio and the canvas height
                    var currentAspectRatio = FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionWidth / (float)
                        FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionHeight;
                    Gum.Wireframe.GraphicalUiElement.CanvasWidth =
                        Gum.Wireframe.GraphicalUiElement.CanvasHeight * currentAspectRatio;

                    var graphicsHeight = Gum.Wireframe.GraphicalUiElement.CanvasHeight;
                    var windowHeight = FlatRedBall.Camera.Main.DestinationRectangle.Height;
                    var zoom = windowHeight / (float)graphicsHeight;
                    if(global::RenderingLibrary.SystemManagers.Default != null)
                    {
                        global::RenderingLibrary.SystemManagers.Default.Renderer.Camera.Zoom = zoom;
                        foreach(var layer in global::RenderingLibrary.SystemManagers.Default.Renderer.Layers)
                        {
                            if(layer.LayerCameraSettings != null)
                            {
                                layer.LayerCameraSettings.Zoom = zoom;
                            }
                        }
                    }
                    ");

        }

        private static void GenerateKeepWindowOnTopCode(ICodeBlock codeBlock)
        {
            codeBlock.Line(@"
#if WINDOWS
        internal static readonly System.IntPtr HWND_TOPMOST = new System.IntPtr(-1);
        internal static readonly System.IntPtr HWND_NOTOPMOST = new System.IntPtr(-2);
        internal static readonly System.IntPtr HWND_TOP = new System.IntPtr(0);
        internal static readonly System.IntPtr HWND_BOTTOM = new System.IntPtr(1);

        [System.Flags]
        internal enum SetWindowPosFlags : uint
        {
            IgnoreMove = 0x0002,
            IgnoreResize = 0x0001,
        }

        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        public struct RECT

        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        [System.Runtime.InteropServices.DllImport(""user32.dll"")]
        [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
        private static extern bool GetWindowRect(System.IntPtr hWnd, out RECT lpRect);

        [System.Runtime.InteropServices.DllImport(""user32.dll"", SetLastError = true)]
        internal static extern bool SetWindowPos(System.IntPtr hWnd, System.IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);

        public static Microsoft.Xna.Framework.Rectangle GetWindowRectangle()
        {
            var hWnd = FlatRedBall.FlatRedBallServices.Game.Window.Handle;

            GetWindowRect(hWnd, out RECT rectInner);

            return new Microsoft.Xna.Framework.Rectangle(
                rectInner.Left,
                rectInner.Top,
                rectInner.Right - rectInner.Left,
                rectInner.Bottom - rectInner.Top);

        }

        public static void SetWindowPosition(int x, int y)
        {
            var hWnd = FlatRedBall.FlatRedBallServices.Game.Window.Handle;
            SetWindowPos(
                hWnd,
                HWND_TOPMOST,
                x, y,
                0, 0, //FlatRedBallServices.GraphicsOptions.ResolutionWidth, FlatRedBallServices.GraphicsOptions.ResolutionHeight,
                SetWindowPosFlags.IgnoreResize
            );
        }

        public static void SetWindowAlwaysOnTop()
        {
            var hWnd = FlatRedBall.FlatRedBallServices.Game.Window.Handle;
            SetWindowPos(
                hWnd,
                HWND_TOPMOST,
                0, 0,
                0, 0, //FlatRedBallServices.GraphicsOptions.ResolutionWidth, FlatRedBallServices.GraphicsOptions.ResolutionHeight,
                SetWindowPosFlags.IgnoreMove | SetWindowPosFlags.IgnoreResize
            );
        }

        public static void UnsetWindowAlwaysOnTop()
        {
            var hWnd = FlatRedBall.FlatRedBallServices.Game.Window.Handle;

            SetWindowPos(
                hWnd,
                HWND_NOTOPMOST,
                0, 0,
                0, 0, //FlatRedBallServices.GraphicsOptions.ResolutionWidth, FlatRedBallServices.GraphicsOptions.ResolutionHeight,
                SetWindowPosFlags.IgnoreMove | SetWindowPosFlags.IgnoreResize
            );
        }
#else
        public static void SetWindowAlwaysOnTop()
            {
                // not supported on this platform, do nothing
            }

            public static void UnsetWindowAlwaysOnTop()
            {
                // not supported on this platform, do nothings
            }

#endif
");
        }

        static List<string> propertyChangesToIgnoreForCodeGeneration = new List<string>
        {
            nameof(DisplaySettingsViewModel.ShowAspectRatioMismatch),
            nameof(DisplaySettingsViewModel.KeepResolutionHeightConstantMessage),
            nameof(DisplaySettingsViewModel.KeepResolutionWidthConstantMessage),
            nameof(DisplaySettingsViewModel.OnResizeUiVisibility),
        };
        public static bool ShouldGenerateCodeWhenPropertyChanged(string propertyName)
        {
            if(propertyChangesToIgnoreForCodeGeneration.Contains(propertyName))
            {
                return false;
            }
            return true;
        }

        private static void GenerateResizeBehaviorEnum(CodeBlockNamespace namespaceContents)
        {
            var enumBlock = namespaceContents.Enum("public", "ResizeBehavior");
            enumBlock.Line("StretchVisibleArea,");
            enumBlock.Line("IncreaseVisibleArea");
        }

        public static void GenerateWidthOrHeightEnum(CodeBlockNamespace namespaceContents)
        {
            var enumBlock = namespaceContents.Enum("public", "WidthOrHeight");
            enumBlock.Line("Width,");
            enumBlock.Line("Height");
        }

        private static void GenerateStaticCameraSetupDefaults(ICodeBlock classContents)
        {
            classContents.Line("public static CameraSetupData Data = new CameraSetupData");
            var block = classContents.Block();
            block.TabCount++;

            var displaySettings = GlueState.Self.CurrentGlueProject.DisplaySettings;

            block.Line($"Scale = {(displaySettings.Scale ).ToString(CultureInfo.InvariantCulture)}f,");
            block.Line($"IsGenerateCameraDisplayCodeEnabled = {(displaySettings.GenerateDisplayCode.ToString().ToLowerInvariant())},");

            block.Line($"ResolutionWidth = {displaySettings.ResolutionWidth},");
            block.Line($"ResolutionHeight = {displaySettings.ResolutionHeight},");
            block.Line($"Is2D = {displaySettings.Is2D.ToString().ToLowerInvariant()},");

            var showAspectRatio =
                displaySettings.AspectRatioBehavior == AspectRatioBehavior.FixedAspectRatio ||
                displaySettings.AspectRatioBehavior == AspectRatioBehavior.RangedAspectRatio;

            if(showAspectRatio)
            {
                decimal aspectRatioValue = 1;

                if(displaySettings.AspectRatioHeight != 0)
                {
                    aspectRatioValue = displaySettings.AspectRatioWidth / displaySettings.AspectRatioHeight;
                }
                block.Line($"AspectRatio = {aspectRatioValue.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()}m,");
            }

            var showAspectRatio2 =
                displaySettings.AspectRatioBehavior == AspectRatioBehavior.RangedAspectRatio;

            if(showAspectRatio2)
            {

                decimal aspectRatioValue = 1;

                if (displaySettings.AspectRatioHeight2 != 0)
                {
                    aspectRatioValue = displaySettings.AspectRatioWidth2 / displaySettings.AspectRatioHeight2;
                }
                block.Line($"AspectRatio2 = {aspectRatioValue.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()}m,");
            }

            block.Line($"IsFullScreen = {displaySettings.RunInFullScreen.ToString().ToLowerInvariant()},");
            block.Line($"AllowWindowResizing = {displaySettings.AllowWindowResizing.ToString().ToLowerInvariant()},");
            block.Line($"TextureFilter = Microsoft.Xna.Framework.Graphics.TextureFilter.{(TextureFilter)displaySettings.TextureFilter},");
            block.Line($"ResizeBehavior = ResizeBehavior.{displaySettings.ResizeBehavior},");

            if(GetIfHasGumProject())
            {
                var scalePercent = displaySettings.ScaleGum;
                if(scalePercent <=0)
                {
                    scalePercent = 100;
                }
                block.Line($"ScaleGum = {(scalePercent).ToString(CultureInfo.InvariantCulture)}f,");
                block.Line($"ResizeBehaviorGum = ResizeBehavior.{displaySettings.ResizeBehaviorGum},");
            }

            block.Line($"DominantInternalCoordinates = WidthOrHeight.{displaySettings.DominantInternalCoordinates},");
            classContents.Line(";");
        }

        private static void GenerateCameraSetupDataClass(CodeBlockNamespace namespaceContents)
        {
            var classBlock = namespaceContents.Class("public", "CameraSetupData");

            classBlock.AutoProperty("public bool", "IsGenerateCameraDisplayCodeEnabled");

            classBlock.AutoProperty("public float", "Scale");
            classBlock.AutoProperty("public float", "ScaleGum");
            classBlock.AutoProperty("public bool", "Is2D");
            classBlock.AutoProperty("public int", "ResolutionWidth");
            classBlock.AutoProperty("public int", "ResolutionHeight");
            classBlock.AutoProperty("public decimal?", "AspectRatio");
            classBlock.AutoProperty("public decimal?", "AspectRatio2");
            classBlock.AutoProperty("public bool", "AllowWindowResizing");
            classBlock.AutoProperty("public bool", "IsFullScreen");
            classBlock.AutoProperty("public ResizeBehavior", "ResizeBehavior");
            classBlock.AutoProperty("public ResizeBehavior", "ResizeBehaviorGum");
            classBlock.AutoProperty("public WidthOrHeight", "DominantInternalCoordinates");
            classBlock.AutoProperty("public Microsoft.Xna.Framework.Graphics.TextureFilter", "TextureFilter");

            classBlock.Line(@"
        public decimal? EffectiveAspectRatio
        {
            get
            {
                if(AspectRatio2 == null)
                {
                    return AspectRatio;
                }
                else if(AspectRatio == null)
                {
                    return AspectRatio2;
                }
                else if(FlatRedBall.FlatRedBallServices.ClientHeight == 0)
                {
                    // just in case:
                    return AspectRatio;
                }
                else
                {
                    // Neither AspectRatio nor 2 are null here

                    var resolutionAspectRatio = FlatRedBall.FlatRedBallServices.ClientWidth / (decimal)FlatRedBall.FlatRedBallServices.ClientHeight;

                    var minAspect = System.Math.Min(AspectRatio.Value, AspectRatio2.Value);
                    var maxAspect = System.Math.Max(AspectRatio.Value, AspectRatio2.Value);

                    if(resolutionAspectRatio < minAspect)
                    {
                        return minAspect;
                    }
                    else if(resolutionAspectRatio > maxAspect)
                    {
                        return maxAspect;
                    }
                    else
                    {
                        // it's begween min and max, so return the resolution aspect ratio
                        return resolutionAspectRatio;
                    }
                }
            }
        }
");

            // set up here

        }

        private static void GenerateSetAspectRatio(ICodeBlock classContents)
        {
            var functionBlock = classContents.Function("private static void", "SetAspectRatioTo",
                "decimal? aspectRatio, WidthOrHeight dominantInternalCoordinates, int desiredWidth, int desiredHeight");
            {
                functionBlock.Line("var resolutionAspectRatio = FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionWidth / (decimal)FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionHeight;");
                functionBlock.Line("int destinationRectangleWidth;");
                functionBlock.Line("int destinationRectangleHeight;");
                functionBlock.Line("int x = 0;");
                functionBlock.Line("int y = 0;");

                var ifBlock = functionBlock.If("aspectRatio == null");
                {
                    ifBlock.Line("destinationRectangleWidth = FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionWidth;");
                    ifBlock.Line("destinationRectangleHeight = FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionHeight;");
                }
                var elseIfBlock = ifBlock.End().ElseIf("aspectRatio > resolutionAspectRatio");
                {
                    elseIfBlock.Line("destinationRectangleWidth = FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionWidth;");
                    elseIfBlock.Line("destinationRectangleHeight = FlatRedBall.Math.MathFunctions.RoundToInt(destinationRectangleWidth / (float)aspectRatio);");

                    elseIfBlock.Line("y = (FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionHeight - destinationRectangleHeight) / 2;");
                }
                var elseBlock = elseIfBlock.End().Else();
                {
                    elseBlock.Line("destinationRectangleHeight = FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionHeight;");
                    elseBlock.Line("destinationRectangleWidth = FlatRedBall.Math.MathFunctions.RoundToInt(destinationRectangleHeight * (float)aspectRatio);");

                    elseBlock.Line("x = (FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionWidth - destinationRectangleWidth) / 2;");
                }

                var foreachBlock = functionBlock.ForEach("var camera in FlatRedBall.SpriteManager.Cameras");
                {

                    foreachBlock.Line("int currentX = x;");
                    foreachBlock.Line("int currentY = y;");
                    foreachBlock.Line("int currentWidth = destinationRectangleWidth;");
                    foreachBlock.Line("int currentHeight = destinationRectangleHeight;");

                    var switchBlock = foreachBlock.Switch("camera.CurrentSplitScreenViewport");
                    {
                        var caseBlock = switchBlock.Case("Camera.SplitScreenViewport.TopLeft")
                            .Line("currentWidth /= 2;")
                            .Line("currentHeight /= 2;");

                        caseBlock = switchBlock.Case("Camera.SplitScreenViewport.TopRight")
                            .Line("currentX = x + destinationRectangleWidth / 2;")
                            .Line("currentWidth /= 2;")
                            .Line("currentHeight /= 2;");

                        caseBlock = switchBlock.Case("Camera.SplitScreenViewport.BottomLeft")
                            .Line("currentY = y + destinationRectangleHeight / 2;")
                            .Line("currentWidth /= 2;")
                            .Line("currentHeight /= 2;");

                        caseBlock = switchBlock.Case("Camera.SplitScreenViewport.BottomRight")
                            .Line("currentX = x + destinationRectangleWidth / 2;")
                            .Line("currentY = y + destinationRectangleHeight / 2;")
                            .Line("currentWidth /= 2;")
                            .Line("currentHeight /= 2;");

                        caseBlock = switchBlock.Case("Camera.SplitScreenViewport.TopHalf")
                            .Line("currentHeight /= 2;");

                        caseBlock = switchBlock.Case("Camera.SplitScreenViewport.BottomHalf")
                            .Line("currentY = y + destinationRectangleHeight / 2;")
                            .Line("currentHeight /= 2;");

                        caseBlock = switchBlock.Case("Camera.SplitScreenViewport.LeftHalf")
                            .Line("currentWidth /= 2;");

                        caseBlock = switchBlock.Case("Camera.SplitScreenViewport.RightHalf")
                            .Line("currentX = x + destinationRectangleWidth / 2;")
                            .Line("currentWidth /= 2;");

                    }

                    foreachBlock.Line("camera.DestinationRectangle = new Microsoft.Xna.Framework.Rectangle(currentX, currentY, currentWidth, currentHeight);");

                    elseIfBlock = foreachBlock.If("dominantInternalCoordinates == WidthOrHeight.Height");
                    {
                        elseIfBlock.Line("camera.OrthogonalHeight = desiredHeight;");
                        elseIfBlock.Line("camera.FixAspectRatioYConstant();");
                    }
                    elseBlock = elseIfBlock.End().Else();
                    {
                        elseBlock.Line("camera.OrthogonalWidth = desiredWidth;");
                        elseBlock.Line("camera.FixAspectRatioXConstant();");
                    }

                }
            }
        }

        private static void GenerateHandleResize(ICodeBlock classContents)
        {
            var functionBlock = classContents.Function("private static void", "HandleResolutionChange", "object sender, System.EventArgs args");
            {
                functionBlock
                    .Line($"SetAspectRatioTo(Data.EffectiveAspectRatio, Data.DominantInternalCoordinates, Data.ResolutionWidth, Data.ResolutionHeight);");

                functionBlock.If("Data.Is2D && Data.ResizeBehavior == ResizeBehavior.IncreaseVisibleArea")
                    .Line("FlatRedBall.Camera.Main.OrthogonalHeight = FlatRedBall.Camera.Main.DestinationRectangle.Height / (Data.Scale/ 100.0f);")
                    .Line("FlatRedBall.Camera.Main.FixAspectRatioYConstant();");

                bool hasGumProject = GetIfHasGumProject();

                if (hasGumProject)
                {
                    functionBlock.Line("ResetGumResolutionValues();");
                }
            }
        }

        private static void GenerateSetupCameraMethodNew(bool generateDisplayCode, ICodeBlock classContents)
        {
            var methodContents = classContents.Function(
                "internal static void",
                "SetupCamera",
                $"Camera cameraToSetUp, Microsoft.Xna.Framework.GraphicsDeviceManager graphicsDeviceManager");

            if (generateDisplayCode)
            {
                methodContents.Line("CameraSetup.graphicsDeviceManager = graphicsDeviceManager;");
                methodContents.Line("FlatRedBall.FlatRedBallServices.GraphicsOptions.TextureFilter = Data.TextureFilter;");
                methodContents.Line("ResetWindow();");
                methodContents.Line("ResetCamera(cameraToSetUp);");

                if(GetIfHasGumProject())
                {
                    methodContents.Line("ResetGumResolutionValues();");
                }

                methodContents.Line(
                    $"FlatRedBall.FlatRedBallServices.GraphicsOptions.SizeOrOrientationChanged += HandleResolutionChange;");
            }
        }

        private static void GenerateResetWindow(bool generateDisplayCode, ICodeBlock classContents)
        {
            var methodContents = classContents.Function(
                "internal static void",
                "ResetWindow",
                "");
            if(generateDisplayCode)
            {

                methodContents.Line("#if WINDOWS || DESKTOP_GL");

                // This needs to come before the fullscreen assignment, because if not it changes the border style
                methodContents.Line($"FlatRedBall.FlatRedBallServices.Game.Window.AllowUserResizing = Data.AllowWindowResizing;");

                string widthVariable = "Data.ResolutionWidth";
                string heightVariable = "Data.ResolutionHeight";
                var ifBlock = methodContents.If("Data.IsFullScreen");
                {

                    ifBlock.Line("#if DESKTOP_GL");

                    // We used to do this on WINDOWS too but that isn't stable so we use borderless
                    // Actually no, we should just use borderless everywhere so it works the same on all platforms:

                    bool useActualFullscreenOnDesktopGl = false;
                    if (useActualFullscreenOnDesktopGl)
                    {
                        ifBlock.Line($"FlatRedBall.FlatRedBallServices.GraphicsOptions.SetFullScreen(Data.ResolutionWidth, Data.ResolutionHeight);");
                    }
                    else
                    {
                        // from here:
                        // http://community.monogame.net/t/how-to-implement-borderless-fullscreen-on-desktopgl-project/8359
                        ifBlock.Line("graphicsDeviceManager.HardwareModeSwitch = false;");

                        // // If the window has been moved to the right, it will be partly off screen when fullscreen. To fix this, move it to the left first:
                        ifBlock.Line(
                            "FlatRedBall.FlatRedBallServices.Game.Window.Position = new Microsoft.Xna.Framework.Point(0,0);");

                        // If in fullscreen we want the widow to take up just the resolution of the screen:
                        ifBlock.Line(
                            "FlatRedBall.FlatRedBallServices.GraphicsOptions.SetResolution(" +
                            "Microsoft.Xna.Framework.Graphics.GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width, " +
                            "Microsoft.Xna.Framework.Graphics.GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height, " +
                            "FlatRedBall.Graphics.WindowedFullscreenMode.FullscreenBorderless);");

                    }

                    ifBlock.Line("#elif WINDOWS");
                    ifBlock.Line("System.IntPtr hWnd = FlatRedBall.FlatRedBallServices.Game.Window.Handle;");
                    ifBlock.Line("var control = System.Windows.Forms.Control.FromHandle(hWnd);");
                    ifBlock.Line("var form = control.FindForm();");

                    ifBlock.Line("form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;");
                    ifBlock.Line("form.WindowState = System.Windows.Forms.FormWindowState.Maximized;");
                    ifBlock.Line("#endif");
                }
                var elseBlock = ifBlock.End().Else();
                {
                    //widthVariable = $"(int)({widthVariable} * Data.Scale/ 100.0f)";
                    //heightVariable = $"(int)({heightVariable} * Data.Scale/ 100.0f)";
                    //elseBlock.Line($"FlatRedBall.FlatRedBallServices.GraphicsOptions.SetResolution({widthVariable}, {heightVariable});");

                    //var width = (int)(Data.ResolutionWidth * Data.Scale / 100.0f);
                    //var height = (int)(Data.ResolutionHeight * Data.Scale / 100.0f);
                    elseBlock.Line($"var width = (int)({widthVariable} * Data.Scale / 100.0f);");
                    elseBlock.Line($"var height = (int)({heightVariable} * Data.Scale / 100.0f);");

                    elseBlock.Line("// subtract to leave room for windows borders");
                    elseBlock.Line("var maxWidth = Microsoft.Xna.Framework.Graphics.GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width - 6;");
                    elseBlock.Line("var maxHeight = Microsoft.Xna.Framework.Graphics.GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height - 28;");

                    elseBlock.Line("width = System.Math.Min(width, maxWidth);");
                    elseBlock.Line("height = System.Math.Min(height, maxHeight);");

                    var innerIf = elseBlock.If("FlatRedBall.FlatRedBallServices.Game.Window.Position.Y < 25");
                    innerIf.Line("FlatRedBall.FlatRedBallServices.Game.Window.Position = new Microsoft.Xna.Framework.Point(FlatRedBall.FlatRedBallServices.Game.Window.Position.X, 25);");

                    elseBlock.Line("FlatRedBall.FlatRedBallServices.GraphicsOptions.SetResolution(width, height);");

                }

                methodContents.Line("#elif IOS || ANDROID");

                // We used to not set the resolution on iOS/Android, but this makes the camera not use the full screen.
                // We want it to do that, so we'll do this:
                // Update November 12, 2015
                // Setting everything to fullscreen makes things render correctly, and also
                // hides the status UI on iOS, but we also need to set the resolution to the
                // native resolution for the cursor to work correctly:
                //methodContents.Line("FlatRedBall.FlatRedBallServices.GraphicsOptions.SetFullScreen(width, height);");
                methodContents.Line(
                    //"FlatRedBall.FlatRedBallServices.GraphicsOptions.SetFullScreen(width, height);"
                    "FlatRedBall.FlatRedBallServices.GraphicsOptions.SetFullScreen(FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionWidth, FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionHeight);"
                    );
                methodContents.Line("#elif UWP");

                methodContents
                    .If("Data.IsFullScreen")
                    .Line($"FlatRedBall.FlatRedBallServices.GraphicsOptions.SetFullScreen(Data.ResolutionWidth, Data.ResolutionHeight);")
                    .End()
                    .Else()
                    .Line($"FlatRedBall.FlatRedBallServices.GraphicsOptions.SetResolution({widthVariable}, {heightVariable});")
                    .Line($"var newWindowSize = new Windows.Foundation.Size({widthVariable}, {heightVariable});")
                    .Line($"Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().TryResizeView(newWindowSize); ")
                    ;

                // closes the #if platform section
                methodContents.Line("#endif");
            }
        }

        private static void GenerateResetMethodNew(bool generateDisplayCode, ICodeBlock classContents)
        {
            classContents.Line("/// Applies resolution and aspect ratio values to the FlatRedBall camera. If Gum is part of the project,");
            classContents.Line("/// then the Gum resolution will be applied. Note that this does not call Layout on the contained Gum objects,");
            classContents.Line("/// so this may need to be called explicitly if ResetCamera is called in custom code.");
            var resetMethod = classContents.Function(
                "internal static void", "ResetCamera", "Camera cameraToReset = null");
            {
                if (generateDisplayCode)
                {
                    resetMethod.If("cameraToReset == null")
                        .Line("cameraToReset = FlatRedBall.Camera.Main;");

                    resetMethod.Line($"cameraToReset.Orthogonal = Data.Is2D;");
                    var ifStatement = resetMethod.If("Data.Is2D")
                        .Line($"cameraToReset.OrthogonalHeight = Data.ResolutionHeight;")
                        .Line($"cameraToReset.OrthogonalWidth = Data.ResolutionWidth;")
                        .Line($"cameraToReset.FixAspectRatioYConstant();")
                    .End().Else()
                        .Line("cameraToReset.UsePixelCoordinates3D(0);")
                        .Line("var zoom = cameraToReset.DestinationRectangle.Height / (float)Data.ResolutionHeight;")
                        .Line("cameraToReset.Z /= zoom; ");

                    resetMethod.Line(
                            $"SetAspectRatioTo(Data.EffectiveAspectRatio, Data.DominantInternalCoordinates, Data.ResolutionWidth, Data.ResolutionHeight);");

                    if(GetIfHasGumProject())
                    {
                        resetMethod.Line("ResetGumResolutionValues();");
                    }
                }
            }
        }

        private static bool GetIfHasGumProject()
        {
            var gumProject = GlueState.Self.CurrentGlueProject
                .GetAllReferencedFiles()
                .FirstOrDefault(item => FlatRedBall.IO.FileManager.GetExtension(item.Name) == "gumx");
            var hasGumProject = gumProject != null;
            return hasGumProject;
        }

        #region Old Code
        private static string GetDisplaySetupOld(ICodeBlock classContents)
        {
            string fileContents = Resources.Resource1.CameraSetupTemplate;
            fileContents = CodeWriter.ReplaceNamespace(fileContents, ProjectManager.ProjectNamespace);

            GenerateSetupCameraMethodOld(classContents);
            GenerateResetCameraMethod(classContents);

            StringFunctions.ReplaceLine(ref fileContents, "// Generated Code:", classContents.ToString());
            return fileContents;
        }

        private static void GenerateResetCameraMethod(ICodeBlock classContents)
        {
            ICodeBlock methodContents = classContents.Function(
                "internal static void", "ResetCamera", "Camera cameraToReset");

            methodContents.Line("cameraToReset.X = 0;");
            methodContents.Line("cameraToReset.Y = 0;");

            methodContents.Line("cameraToReset.XVelocity = 0;");
            methodContents.Line("cameraToReset.YVelocity = 0;");

            // We can't detach because by this point the Camera may already
            // be attached to an Entity:
            //methodContents.Line("cameraToReset.Detach();");
            // November 6, 2015
            // I wondered why we
            // didn't do this until
            // I saw this comment. I'm
            // probably not going to be
            // the only one, so let's put
            // some info here:
            methodContents.Line("// Glue does not generate a detach call because the camera may be attached by this point");
            // I wondered "but why doesn't
            // the ResetCamera method get called
            // earlier, before the Camera has a chance
            // to attach itself to an entity. The reason
            // is because we can't do things to the camera
            // prior to AddToManagers because the camera may
            // be used in the previous screen if this screen is
            // loading async.

        }

        private static void GenerateSetupCameraMethodOld(ICodeBlock classContents)
        {
            //internal static void SetupCamera(Camera cameraToSetUp, GraphicsDeviceManager graphicsDeviceManager)

            // for 360, which doesn't support optional parameters.
            ICodeBlock methodContents = classContents.Function(
                "internal static void",
                "SetupCamera",
                string.Format("Camera cameraToSetUp, GraphicsDeviceManager graphicsDeviceManager",
                    ProjectManager.GlueProjectSave.ResolutionWidth,
                    ProjectManager.GlueProjectSave.ResolutionHeight));
            methodContents.Line(string.Format("SetupCamera(cameraToSetUp, graphicsDeviceManager, {0}, {1});", ProjectManager.GlueProjectSave.ResolutionWidth,
                    ProjectManager.GlueProjectSave.ResolutionHeight));

            methodContents = classContents.Function(
                "internal static void",
                "SetupCamera",
                "Camera cameraToSetUp, GraphicsDeviceManager graphicsDeviceManager, int width, int height");

            methodContents.TabCount = 3;

            AddSetResolutionCode(methodContents);

            AddUsePixelCoordinatesCode(methodContents);
        }

        private static void AddUsePixelCoordinatesCode(ICodeBlock methodContents)
        {
            if (ProjectManager.GlueProjectSave.In2D)
            {
                if (ProjectManager.GlueProjectSave.SetOrthogonalResolution)
                {
                    methodContents.Line(string.Format("cameraToSetUp.UsePixelCoordinates(false, {0}, {1});",
                                                      ProjectManager.GlueProjectSave.OrthogonalWidth,
                                                      ProjectManager.GlueProjectSave.OrthogonalHeight));
                }
                else
                {
                    methodContents.Line("cameraToSetUp.UsePixelCoordinates();");
                }
            }
        }

        private static void AddSetResolutionCode(ICodeBlock methodContents)
        {
            if (ProjectManager.GlueProjectSave.SetResolution)
            {
                bool pcOnlySetResolution = ProjectManager.GlueProjectSave.ApplyToFixedResolutionPlatforms == false;

                methodContents.Line("#if WINDOWS");

                if (ProjectManager.GlueProjectSave.RunFullscreen)
                {
                    methodContents.Line("FlatRedBall.FlatRedBallServices.GraphicsOptions.SetFullScreen(width, height);");

                }
                else
                {

                    methodContents.Line("FlatRedBall.FlatRedBallServices.GraphicsOptions.SetResolution(width, height);");
                }

                methodContents.Line("#elif IOS || ANDROID");

                // We used to not set the resolution on iOS/Android, but this makes the camera not use the full screen.
                // We want it to do that, so we'll do this:
                // Update November 12, 2015
                // Setting everything to fullscreen makes things render correctly, and also
                // hides the status UI on iOS, but we also need to set the resolution to the
                // native resolution for the cursor to work correctly:
                //methodContents.Line("FlatRedBall.FlatRedBallServices.GraphicsOptions.SetFullScreen(width, height);");
                methodContents.Line(
                    //"FlatRedBall.FlatRedBallServices.GraphicsOptions.SetFullScreen(width, height);"
                    "FlatRedBall.FlatRedBallServices.GraphicsOptions.SetFullScreen(FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionWidth, FlatRedBall.FlatRedBallServices.GraphicsOptions.ResolutionHeight);"
                    );

                // closes the #if platform section
                methodContents.Line("#endif");

                methodContents.Line("#if WINDOWS_PHONE || WINDOWS_8 || IOS || ANDROID");

                var ifBlock = methodContents.If("height > width");
                {
                    ifBlock.Line("graphicsDeviceManager.SupportedOrientations = DisplayOrientation.Portrait;");
                }
                var elseBlock = ifBlock.End().Else();
                {
                    elseBlock.Line("graphicsDeviceManager.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;");
                }

                methodContents.Line("#endif");
            }
        }

#endregion
    }
}


Once again time is flying by, can hardly believe we are into December already, before we know it it will be 2014!
It has been another busy, successful year here at Cake. Loads of new yummy products have been launched and we have some exciting new customers now on board!
As mentioned in last months blog, we are in the middle of planning our stand at Scotland's Speciality Food Fair at the Secc in January. Plans are coming along nicely and we are looking forward to meeting those of you who are able to come along!
We have also booked up for some other shows in 2014 which are located across the UK, more info will be posted on these events shortly.
As always our NPD team are working hard to keep our product range fresh and innovative and once again they have come up with a new exciting traybake - The Caramel Cabana!! This will be launched within the next couple of weeks so please look out for it on our 'New Products' page!
As always we have a great Telesales Team on hand to help with any questions or queries so please give them a call on 0141 880 8075.
We hope you all have a lovely time over the festive period and look forward to another busy year in 2014!


Cashmio Casino was launched in 2015 and is operated by MT Secure Trade Limited. Offering casino games from a host of big name providers such as Netent, Micrograming, Play 'n Go and Thunderkick, the Cashmio website is a welcome departure from your typical online gaming platform.
Heralding itself as the 'World's Happiest Casino', Cashmio really tries to live up to its own playful epithet. The design is fun and bears a strong resemblance to the Casumo website. Each page is broken down into coloured sections that beautifully integrate the game art while promoting their latest in-game offers and bonuses. Although the home page shies away from the traditional header-menu-game lobby structure, the site's game section features a more typical game lobby layout.
Each game thumbnail is framed in a rounded box and accompanied by minimum bet, max bet and pay-line information. For progressive slots, the latest jackpots are also included. All games load in a Flash-based browser – its background is decorated with game artwork during play which makes for a truly immersive game experience.
The Cashmio Casino website clearly sits on a powerful framework, with the pages loading quickly, the games running smoothly and a noticeable lack of lazy load. So when you scroll down the game pages on the main websites, you don't have to wait for game thumbnails to load as you scroll. Demo play is also available without having to log in.
During our testing we made heavy use of the game filter which allows players to search for games according to provider, theme and feature. When you boast this many casino games, having such a function can be of huge benefit to the user.
There are currently four live games which can be found in the table game section: two versions of roulette and two blackjack games. Their Blackjack Pro game features a £75,000 maximum bet ceiling.
Cashmio is fully responsive and works across all devices. The mobile version is similar to the main website in look and feel but doesn't include quite as many games (250 compared to 500+). Nevertheless, it includes a filter tool which allows for scroll-less browsing and makes 'gaming on the go' that much more convenient.
At present, Cashmio does not offer any kind of VIP scheme or package – unusual to say the least.
Cashmio is a superbly conceived website that offers an outstanding user experience. Visually, it's like a slightly more subdued version of the Casumo website and doesn't have quite as much going on as its more illustrious counterpart. Cashmio also takes a similar, 'fun and wacky' approach which belies the often 'feverish and desperate' nature of online casino play. The lack of a VIP package or loyalty system was disappointing as was the lack of telephone support. With that being said, it's so refreshing to visit a casino website, whose designers have opted to break from the norm and create a casino platform that's original and innovative.


text:
Editorial: Global outbreaks should be an issue before they affect us
Home /Opinion/Editorial: Global outbreaks should be an issue before they affect us
Sarah Allisot
Nobody likes being sick. Noticing that a friend is coughing is reason enough to ostracize them and cover yourself in hand sanitizer. Diseases are aptly noticed on campus, whether it's our everyday campus plague which hits every semester or larger flare ups that enter the United States. If a virus hits the U.S., news outlets explode with coverage: noting symptoms, warning signs and projected spread of the virus. We pull together as a nation to collectively worry and push for a cure. This process is good; the underlying motive to worry only when it gets to us is an isolating and indifferent approach to global interaction.
Zika virus is our most recent global health emergency. It emerged in Brazil in September of last year when doctors noticed unusual upticks in congenital birth defects. It took nearly six months for the World Health Organization (WHO) to declare a global public health emergency on Feb. 2, 2016. Around that same time, a case of Zika virus was confirmed in a man residing in Dallas, Texas. Once established in our country, research and funding have become high priorities. A projected $1.8 billion has been estimated for research costs toward vaccinations.
The inclination to worry about something when it becomes a problem is prevalent to most venues of life, from cramming for exams to widespread diseases. However, making something an issue only once it directly affects us is far from empathy and compassion. We reacted to the Ebola virus in the same manner. Once that virus was "solved" for us, we moved on with our lives. Do a quick search for Ebola, and results will tell you it is almost gone. In U.S. media, scarcely a word can be heard. The problem is geographically beyond us, so it no longer exists in our media. However, WHO will continue to work on preventative measures against the virus into mid-2016.
How we currently approach outbreaks, we miss the crucial beginning and ending stages of solving the issue. There is an understandable gap of reaction while an outbreak is defined and properly noticed which keeps us from reacting immediately. But those months we hold back while foreign countries are suffering are detrimental to global relations and the overall impact of a virus. Problems exist outside of our immediate vicinity, even if we don't like to think about them. It would be far better overall for us to involve ourselves before an outbreak spreads and the subsequent mad dash ensues.
Our American-centric standpoint shuts our entire country into a bubble and mutes issues until they potentially cause a problem for us. Once it touches our bubble, it matters. We rally and "defeat" the threat. The scope for that defeat only extends to our borders. Anything beyond once again goes quiet. There is nothing inherently wrong with worrying, especially about our country's safety. It is the shutdown of response to tragedies in other places of the world which brings up red flags. We cannot decide something is over just because it's not bothering us anymore.
Undergraduate research fellows speak on sustainability
Tip Whip debuts mobile app now available for UMaine students on iOS and Android
Letter to the Editor by…
Caption by Liv Schanck
UMaine Dining in shambles with…
Image from Los Angeles Times
Will Smith no longer needs…
Graphic by Liv Schanck
Prioritizing your mental health heading…
The great decline of reading
Letters from the Dean –…
How many more people will…
Graphic by Brianna Neely
'Black Panther: Wakanda Forever' offers…

redpajama_set_name: RedPajamaCommonCrawl


text:
Epics & Folklore A-Z
Literature: Epics & Folklore A-Z
Authors Toggle Dropdown
Featured Authors: A-E
Featured Authors: F-L
Featured Authors: M-R
Featured Authors: S-Z
Drama Toggle Dropdown
Plays A-L
Plays M-Z
Novels & Novellas Toggle Dropdown
Novels A-L
Novels M-Z
Poetry Toggle Dropdown
Poetry A-L
Poetry M-Z
Short Stories Toggle Dropdown
Short Stories A-L
Short Stories M-Z
Nonfiction Toggle Dropdown
Nonfiction A-L
Nonfiction M-Z
Epics & Folklore Toggle Dropdown
Graphic Novels, Comics Art, & Manga
Folklore, Fables, & Fairy Tales: Works Currently Featured
"Bluebeard" by Charles Perrault
"Death Has an Appointment in Samarra" (Sufi Fable)
"Fox and the Grapes" by Aesop
"Godfather Death" by Jakob and Wilhelm Grimm
"Independence" by Chuang Tzu
Epics: Works Currently Featured
Epic of Gilgamesh
The Iliad by Homer
The Odyssey by Homer
Song of Roland
Overview, Background, Characters, & Analysis
Critical Articles
"Beowulf" in Poetry for Students by edited by Elizabeth Thomason
Provides analysis of the most frequently studied poems in literature courses. Contains author biography, poem summary, themes, style, historical context, critical overview, and criticism.
"Blurred Lines: Does Religious Polarity Create Problematic Heroes in the Poem, Beowulf?" by Elizabeth Bell Canon
The article recognizes the common analysis of Beowulf, Old English epic poem, which focuses on tension between the pagan and the Christian themes in the poem. It further discusses how common it would have been for early Christians to move "from pagan to Christian in a zig-zag pattern" that models the very structure of tire narrative. It mentions the times when the characters revert to pagan traditions and the times when they embrace Christian ethics.
Beowulf Basic Readings by Peter S. Baker (Editor)
Gathering some of the most important studies from the past 25 years of "Beowulf" scholarship, "The Beowulf Reader" offers essential insights both to scholars in the field and to readers coming to this Old English literary masterpiece for the first time. The carefully selected essays in this volume represent the various approaches that have dominated recent Beowulf studies and illustrate the evolution of Old English literary criticism, from New Critical formalism to recent trends in critical theory and a resurgent historicism.
The Beowulf poet; : a collection of critical essays by edited by Donald K. Fry
Call Number: PR1585 .F7
Collection of critical essays on style, characters, thematic elements, and more.
Seamus Heaney on the New Beowulf
Recently re-translated by Nobel Laureate Seamus Heaney, Beowulf has caused a sensation in both the U.S. and the U.K. In this program, NewsHour correspondent Elizabeth Farnsworth speaks with Heaney about his attraction to that epic poem, the probable background of the bard who created the original, similarities between Old English and bits of Anglo-Saxon that still crop up in rural Ireland, and the importance of meter and alliteration in driving the poem. A reading of a passage from the new text and the old demonstrates the poetic affinity between them while underscoring the poem's timeless appeal. (12 minutes)
Beowulf and the Roots of Anglo-Saxon Poetry
Beowulf is the oldest written epic in English literature. In this program, Dr. Robert DiNapoli—teaching fellow in Old and Middle English at the University of Birmingham, England—and Professor John Burrow of Bristol University examine the symbolism and the influence of Christianity in Beowulf and other masterpieces of English and Germanic poetry. The Wanderer, The Seafarer, The Dream of the Rood, and The Battle of Maldon are also analyzed. The program is an indispensable aid in teaching this watershed period in Western literature. (31 minutes)
Monsters and Heroes in Beowulf
This online article is part of a multimedia presentation featured with the British Library's online exhibit of the digitized medieval manuscripts.
Beowulf by Seamus Heaney (translator); Daniel Donoghue (editor)
Call Number: PR1583 .H43 2002
The translation that "rides boldly through the reefs of scholarship" (The Observer) is combined with first-rate annotation. No reading knowledge of Old English is assumed. Heaney's clear and insightful introduction to Beowulf provides students with an understanding of both the poem's history in the canon and Heaney's own translation process.
Beowulf by Kevin Crossley-Holland (Translator); Heather O'Donoghue (Editor)
Beowulf is the longest and finest literary work to have come down to us from Anglo-Saxon times, and one of the world's greatest epic poems. Set in the half-legendary, half historical Scandinavian past, it tells the story of the hero Beowulf, who comes to the aid of the Danish king Hrothgar by killing first the terrifying, demonic monster Grendel, and then Grendel's infuriated and vengeful mother. A lifetime later, Beowulf's own kingdom, Geatland, isthreatened by a fiery dragon; Beowulf heroically takes on this challenge, but himself dies killing the dragon.The poem celebrates the virtues of the heroic life, but Hrothgar and Beowulf are beacons of wisdom and courage in a dark world of feuds, violence and uncertainty, and Beowulf's selfless heroism is set against a background of ruthless power struggles, fratricide and tyranny.
Opera Easy: La Cenerentola
In this program, host Natalie Choquette informs viewers that [another] famous Charles Perrault fairy-tale of Cinderella is the basis for this rollickingly funny opera by Rossini.
Bluebeard: a reader's guide to the English tradition by Casie E. Hermansson
Bluebeard is the main character in one of the grisliest and most enduring fairy tales of all time. A serial wife murderer, he keeps a horror chamber in which remains of all his previous matrimonial victims are secreted from his latest bride. She is given all the keys but forbidden to open one door of the castle. Astonishingly, this fairy tale was a nursery room staple, one of the tales translated into English from Charles Perrault's French Mother Goose Tales. Bluebeard: A Reader's Guide to the English Tradition is the first major study of the tale and its many variants (some, like "Mr. Fox," native to England and America) in English: from the eighteenth- and nineteenth-century chapbooks, children's toybooks, pantomimes, melodramas, and circus spectaculars, through the twentieth century in music, literature, art, film, and theater. Chronicling the story's permutations, the book presents examples of English true-crime figures, male and female, called Bluebeards, from King Henry VIII to present-day examples. Bluebeard explores rare chapbooks and their illustrations and the English transformation of Bluebeard into a scimitar-wielding Turkish tyrant in a massively influential melodramatic spectacle in 1798. Following the killer's trail over the years, Casie E. Hermansson looks at the impact of nineteenth-century translations into English of the German fairy tales of the Brothers Grimm, and the particularly English story of how Bluebeard came to be known as a pirate.
"Death Has an Appointment in Samarra (Sufi Fable)"
Overview, Background, Characters, and Analysis
Archetypes and Motifs in Folklore and Literature by Jane Garry; Hasan El-Shamy
Call Number: GR72.56 .A73 2005
available in Print & eBook forms
W. Somerset Maugham's 1933 retelling of "Death Has an Appointment in Samarra (Sufi Fable)."
Includes a link to a study guide for further thought and discussion.
The Epic of Gilgamesh
Gilgamesh among Us by Theodore Ziolkowski
The world's oldest work of literature, the Epic of Gilgamesh recounts the adventures of the semimythical Sumerian king of Uruk and his ultimately futile quest for immortality after the death of his friend and companion, Enkidu, a wildman sent by the gods. Gilgamesh was deified by the Sumerians around 2500 BCE, and his tale as we know it today was codified in cuneiform tablets around 1750 BCE and continued to influence ancient cultures--whether in specific incidents like a world-consuming flood or in its quest structure--into Roman times. The epic was, however, largely forgotten, until the cuneiform tablets were rediscovered in 1872 in the British Museum's collection of recently unearthed Mesopotamian artifacts. In the decades that followed its translation into modern languages, the Epic of Gilgamesh has become a point of reference throughout Western culture. In Gilgamesh among Us, Theodore Ziolkowski explores the surprising legacy of the poem and its hero, as well as the epic's continuing influence in modern letters and arts.
Male and Female in the Epic of Gilgamesh by Tzvi Abusch
The deeds and struggles of Gilgamesh, legendary king of the city-state Uruk in the land of Sumer, have fascinated readers for millennia. They are preserved primarily in the Epic of Gilgamesh, one of the most well-known pieces of Mesopotamian literature. Studying the text draws us into an orbit that is engaging and thrilling, for it is a work of fantasy and legend that addresses some of the very existential issues with which contemporary readers still grapple. We experience the excitement of trying to penetrate the mind-set of another civilization, an ancient one--in this instance, a civilization that ultimately gave rise to our own. The studies gathered here all demonstrate Tzvi Abusch's approach to ancient literature: to make use of the tools of literary, structural, and critical analysis in service of exploring the personal and psychological dimensions of the narration. The author focuses especially on the encounters between males and females in the story. The essays are not only instructive for understanding the Epic of Gilgamesh, they also serve as exemplary studies of ancient literature with a view to investigating streams of commonality between ancient times and ours.
Gilgamesh by John Maier
Call Number: PJ3771 .G6 G55 1997
25 Interpretive Studies on Gilgamesh and a Comprehensive Bibliography with over 1500 entries, Gilgamesh: A Reader is a collection designed to: -- Enrich the reader's background information on the epic-- Help draw connections between Gilgamesh and other literature-- Stimulate thought and discussion-- Enliven interest in Gilgamesh
Male and female in the epic of Gilgamesh : encounters, literary history, and interpretation
Offers a variety of critical essays examining the cultural context, comparisons to other ancient literature, and analysis of the the work.
The foundation of existentialism in the oldest story ever told: The Epic of Gilgamesh
The Epic of Gilgamesh is considered as one of the first stories ever told, which dates back to approximately 3,000 B.C. Yet, this ancient story addresses some of the basic premises of existentialism, particularly as explored in the works of Kierkegaard, Buber, and Heidegger. This paper is an existential analysis of the story, its hero, and the deeper messages of this timeless portrayal of grappling with death and search for meaning, whose many lessons pertain aptly to the struggles of the 21st century human existence. It also, convincingly, conveys the message that what we refer to as existentialism is perhaps as old as humanity itself, and not simply a product of the 19th or the 20th century. This 'voice' from the distant past calls us to approach life in an engaged, passionate manner, while fully remaining aware of its uncertain, ephemeral nature.
The development and meaning of the Epic of Gilgamesh: an interpretive essay
This essay traces the history of the several major versions (Old Babylonian, eleven-tablet, and twelve-tablet) of the Akkadian Epic of Gilgamesh and examines the development of meaning from one version to the next. The focus is on the underlying conflict or conflicts that define and impart power to the work, that is, the conflict between the extraordinary and the normal. We will notice that in the Epic there is a constant conflict between the heroic values that the warrior-hero Gilgamesh represents and those other existential values that defined Mesopotamian culture and that appear in the Epic in the form of Gilgamesh's several non-heroic identities: in the Old Babylonian version, the conflict is that of hero versus man; in the eleven-tablet version that of hero versus king; and in the twelve-tablet version that of hero versus god.
Looking for more critical articles? Start with a quick catalog search below, or try one of our literature databases.
The Epic of Gilgamesh by Annenberg Learner (Firm)
The first known human story is that of Gilgamesh, king of Uruk. Images of artifacts from ancient Iraq mix with beautiful illustrations, dance, and costume to tell of the relations between gods and mortals, the search for friendship, love, and immortality.
The Epic of Gilgamesh by Sumaya Shabandar (Translator); Rakan Dabdoub (Illustrator)
Call Number: PJ3771 .G5 E5 1994
This ancient Mesopotamian epic is thought to be 4000 years old and may rightly be called the Odyssey of ancient Iraq. It has been placed by literary experts in the ranks of the world's greatest literature. Believed to have been based on a real ruler from 7th century BCE, it tells a tale of a young ruler, his wild adventures with his raucous friend, his friend's death, confrontations with enemies from the human, animal and divine realms and the tale of the Great Flood and themes of loss of innocence and the quest for immoratality. This important new translation is presented in verse form so as to remain faithful to the original. It is accompanied by twelve illustrations by the Iraqi artist Rakan Dabdoub.
The Epic of Gilgamesh by Danny P. Jackson (Translator); Thom Kapheim (Illustrator); Robert D. Biggs (Introduction by)
Call Number: PJ3771.G5 E5 1992
"With evidence of its existence dating back nearly 4,000 years, The Epic of Gilgamesh is without question the world's oldest known epic, predating the works of Homer and Vergil by many centuries." "The work is not only a historical landmark, but a literary and philosophical one as well. A great flood, paradise lost and a quest for immortality figure prominently in the text, marking it as the first of the mythological parallels to the Bible. Versions of the story made their way into many cultures throughout the ancient world and its universal themes are issues which continue to preoccupy you and me." "The tale follows Gilgamesh the king as he is transformed from a powerful and arrogant ruler to a man who has been forced by the realities of life to confront and accept his own mortality. It is a compelling tale, filled with drama, passion and pathos."
The Epic of Gilgamesh: an English version, with an introduction by N. K. Sandars (Foreword by, Translator); Penguin Editors (Editor); Andrew George
Call Number: PJ3771.G5E5 1972
Gilgamesh, King of Uruk, and his companion Enkidu are the only heroes to have survived from the ancient literature of Babylon, immortalized in this epic poem that dates back to the 3rd millennium BC. Together they journey to the Spring of Youth, defeat the Bull of Heaven and slay the monster Humbaba. When Enkidu dies, Gilgamesh's grief and fear of death are such that they lead him to undertake a quest for eternal life. A timeless tale of morality, tragedy and pure adventure, The Epic of Gilgamesh is a landmark literary exploration of man's search for immortality.
An Old Babylonian Version of the Gilgamesh Epic by Morris Jastrow & Albert T. Clay (translators)
"The Fox and the Grapes" by Aesop
Aesopic Conversations by Leslie Kurke
Examining the figure of Aesop and the traditions surrounding him, Aesopic Conversations offers a portrait of what Greek popular culture might have looked like in the ancient world. What has survived from the literary record of antiquity is almost entirely the product of an elite of birth, wealth, and education, limiting our access to a fuller range of voices from the ancient past. This book, however, explores the anonymous Life of Aesop and offers a different set of perspectives. Leslie Kurke argues that the traditions surrounding this strange text, when read with and against the works of Greek high culture, allow us to reconstruct an ongoing conversation of "great" and "little" traditions spanning centuries. Delving into Aesop, his adventures, and his crafting of fables, Aesopic Conversations shows how this low, noncanonical figure was--unexpectedly--central to the construction of ancient Greek literature.
This site features illustrated versions of 39 of Aesop's fables. Some of the tales have been animated to enhance the experience.
Aesop's Fables by S. A. Handford; D. L. Ashliman (Introduction by, Intro and Notes by); Aesop Staff; V. S. Vernon Jones (Translator); Arthur Rackham (Illustrator)
Call Number: PA3855 .E5 2005
As legend has it, the storyteller Aesop was a slave who lived in ancient Greece during the sixth century B.C. His memorable, recountable fables have brought amusing characters to life and driven home thought-provoking morals for generations of listeners and modern-day readers. Translated into countless languages and familiar to people around the world, Aesop's fables never tarnish despite being told again and again. This collection presents nearly 300 of Aesop's most entertaining and enduring stories.
Straparola and the fairy tale: between literary and oral traditions
Against Ruth B. Bottigheimer's argument that the sixteenth-century Italian author Giovanni Francesco Straparola originated fairy tale in its best-known form, this article maintains that ancient and medieval texts contain earlier literary adaptations of folktales that qualify as fairy tales.
"Happily Ever After: The folk tales gathered by the Brothers Grimm not only enchant us; they record the hardships European families endured for centuries." by Wendy Smith
Click the full-text link to access this article.
Discusses the meanings and usage of Grimm's tales.
The Grimm Brothers' Home Page
Resource for all things Grimm. Includes biographical information, translations, bibliographies, and links to additional resources.
Godfather Death: tales of Aarne-Thompson-Uther type 332
Includes multiple version of the same tale in different countries and cultural contexts with notes on translation and more.
The Annotated Brothers Grimm by Jacob Grimm; Wilhelm K. Grimm; Maria Tatar; A. S. Byatt (Introduction by)
Call Number: PT921 .K5613 2004
The Annotated Brothers Grimm celebrates the richness and dramatic power of the legendary fables in the most spectacular and unusual Grimm volume in decades. Containing forty stories in new translations by Maria Tatar—including "Little Red Riding Hood," "Cinderella," "Snow White," and "Rapunzel"—the book also features 150 illustrations, many of them in color, by legendary painters such as George Cruikshank and Arthur Rackham; hundreds of annotations that explore the historical origins, cultural complexities, and psychological effects of these tales; and a biographical essay on the lives of Jacob and Wilhelm Grimm. Perhaps most noteworthy is Tatar's decision to include tales that were previously excised, including a few bawdy stories and others that were removed after the Grimms learned that parents were reading the book to their children—stories about cannibalism in times of famine and stories in which children die at the end. Enchanting and magical, The Annotated Brothers Grimm will cast its spell on children and adults alike for decades to come.
"The Iliad" in Literary Themes for Students: War and Peace by Anne Marie Hacht (ed.)
Examines dominant and recurring subthemes in the literature of war; including survival, terrorism, leadership, and genocide. Includes extended plot summary, historical and critical overview, discussion of basic themes, and critical excepts.
"The Age of Homeric Epic" in Arts and Humanities Through the Eras by Edward I. Bleiberg, et al.
Profiling milestones in Ancient Rome and Greece from 1200 B.C.E. though 476 C.E.
"The Iliad and History" by Andrew Dalby
In the following essay, Dalby surveys archaeological finds, geographic markers, and linguistic evidence to formulate a plausible explanation for the oral tradition that gave rise to the Iliad.
"Mourning Rights: Beowulf, the Iliad, and the War in Iraq" by Robin Norris
n the following essay, the circumstances of the Iraq War prompt Norris to reflect upon the contemporary significance of Beowulf and the Iliad and what they have to say about death, immortality, and mourning.
Exploration & Colonization (Bloom's Literary Themes)
Call Number: PN56.C63E97 2010
Includes Charles Moorman's "The Iliad" from Kings and Captains: variations on a heroic theme (1971)
Alienation (Bloom's Literary Themes) by Harold Bloom; Blake Hobby (Editor)
Call Number: PN56.A45 A45 2009
Includes Scott F. Crider's essay on Homer's epic The Iliad "The solitary amphora: alienation and tradition in Homer's Iliad"
Homer's the Iliad by Harold Bloom (Introduction by)
Call Number: PA4037.A5 H8 1987
A collection of essays on the classic Greek epic of the Trojan War, arranged in chronological order of publication.
In Search of the Trojan War Series
This six-part series, filmed in Greece, Turkey, and Berlin, features charismatic historian Michael Wood who attempts to discover whether there was any truth in Homer's epic poems. Is Hissalik the site of the mighty Troy? Did Helen, Achilles, and Agamemnon ever exist? What was the significance of the famous wooden horse? Prepare for dramatic new twists to the tale. (6 videos, 59-60 minutes each)
Homer's Iliad and Odyssey
The heroes of Homer's Iliad and Odyssey were the Greek ideal. Cleisthenes took tales of mythical heroes to heart. PBS. (2:32)
The Odyssey and the Iliad
Viewers see an excerpt from "The Odyssey" (Director Andrey Konshalovsky). The Mediterranean is the landscape of Western Literature's first works: Homer's Iliad and Odyssey. They have "magnificent plots" that Stephen Fry shares with us. A BBC Production. (4:08)
One of the oldest extant works of Western literature, the Iliad is a timeless epic poem of great warriors trapped between their own heroic pride and the arbitrary, often vicious decisions of fate and the gods. Renowned scholar and acclaimed translator Peter Green captures the Iliad in all its surging thunder for a new generation of readers. Featuring an enticingly personal introduction, a detailed synopsis of each book, a wide-ranging glossary, and explanatory notes for the few puzzling in-text items, the book also includes a select bibliography for those who want to learn more about Homer and the Greek epic. This landmark translation--specifically designed, like the oral original, to be read aloud--will soon be required reading for every student of Greek antiquity, and the great traditions of history and literature to which it gave birth.
"Taoism." Worldmark Encyclopedia of Religious Practices.
Historical overview of Taoism.
Zhuangzi (Chuang-Tzu, 369—298 B.C.E.)
Background and historical context for the works and teachings of Zhuangzi (Chuang-Tzu).
The Complete Works of Zhuangzi by Burton Watson (Translator)
Only by inhabiting Dao (the Way of Nature) and dwelling in its unity can humankind achieve true happiness and freedom, in both life and death. This is Daoist philosophy's central tenet, espoused by the person -- or group of people -- known as Zhuangzi (369?-286? B.C.E.) in a text by the same name. To be free, individuals must discard rigid distinctions between good and bad, right and wrong, and follow a course of action not motivated by gain or striving. When one ceases to judge events as good or bad, man-made suffering disappears and natural suffering is embraced as part of life. Zhuangzi elucidates this mystical philosophy through humor, parable, and anecdote, deploying non sequitur and even nonsense to illuminate a truth beyond the boundaries of ordinary logic. Boldly imaginative and inventively worded, the Zhuangzi floats free of its historical period and society, addressing the spiritual nourishment of all people across time. One of the most justly celebrated texts of the Chinese tradition, the Zhuangzi is read by thousands of English-language scholars each year, yet only in the Wade-Giles romanization. Burton Watson's pinyin romanization brings the text in line with how Chinese scholars, and an increasing number of other scholars, read it.
Disguise and Recognition in the Odyssey by Sheila Murnaghan
Disguise and Recognition in the Odyssey reveals the significance of the Odyssey's plot, in particular the many scenes of recognition that make up the hero's homecoming and dramatize the cardinal values of Homeric society, an aristocratic culture organized around recognition in the broader senses of honor, privilege, status, and fame. Odysseus' identity is seen to be rooted in his family relations, geographical origins, control of property, participation in the social institutions of hospitality and marriage, past actions, and ongoing reputation. At the same time, Odysseus' dependence on the acknowledgement of others ensures attention to multiple viewpoints, which makes the Odyssey more than a simple celebration of one man's preeminence and accounts in part for the poem's vigorous afterlife. The theme of disguise, which relies on plausible lies, highlights the nature of belief and the power of falsehood and creates the mixture of realism and fantasy that gives the Odyssey its distinctive texture. The book contains a pioneering analysis of the role of Penelope and the questions of female agency and human limitation raised by the critical debate about when exactly she recognizes that Odysseus has come home.
""The Devious Narrator of the Odyssey"" by Scott Richardson
In the following essay, Richardson enumerates the ways in which the narrator of the Odyssey misleads readers, likening this deviousness to that of Odysseus. Richardson argues that the narrator's untrustworthiness reflects "the instability and unreliability that characterize the world of the Odyssey."
"Homer's Odyssey: Penelope and the case for early recognition" by John B. Vlahos
For over a thousand years, beginning with renewed interest in Homeric studies in ninth-century Constantinople, Homer's readers have been taught what has become the "standard interpretation," that Penelope does not recognize the beggar to be her husband until the so called "test of the bed" in book 23. This interpretation was accepted without question in the West for centuries until challenged for the first time, as far as we know, near the mid-twentieth century by A.M. Harmon of Yale University, who in 1939 presented a case for early recognition in an unpublished address delivered before the American Philological Association at Ann Arbor, Michigan (Post, 275, note 18). (1) Subsequently, Philip Whaley Harsh, in a revolutionary article published in the American Journal of Philology in 1950, suggested that Penelope suspects in book 19 that the beggar in her hall is in fact her husband, Odysseus, in disguise. Recognition prior to book 23, such as suggested by Harmon and Harsh, is commonly referred to as "early recognition." As Robert Fitzgerald points out in the postscript to his translation of the Odyssey, the standard interpretation of the role Penelope and Odysseus play in book 19 is that of lady and beggar, nothing more (1963, 503). I will attempt to show, however, that the standard interpretation is not necessarily what Homer intended; it diminishes the poet's genius and renders Penelope's failure of recognition inconsistent with the cunning and circumspection she displays throughout the poem.
Homer: a collection of critical essays by edited by George Steiner and Robert Fagles
Call Number: PA4037 .A5 S7
Collection of critical essays focused on Homer's epic poem The Odyssey and his treatment of Ulysses.
Homer's The Odyssey by Harold Bloom (Introduction by)
Call Number: PA4167.H66
A collection of seven critical essays on Homer's epic poem, arranged chronologically in order of their original publication.
Contemporary Western society revolves around celebrity—and ancient Greek culture was no different, as this program demonstrates with perceptive comparisons of the two worlds. Scholarly analysis and splendid reenactments bring new life to Homer's epic, giving it both a historical and personal context. For long-ago Greek listeners enraptured with famous warriors and athletes, Homer fashioned a subtle moral dilemma: can one pursue fortune and recognition without endangering a far more valuable treasure—namely, the love and stability of family? Clearly, The Odyssey still engenders sociologically relevant discussion. A BBCW Production. (51 minutes)
A Critical Guide to The Odyssey
It is said that every road movie and novel about a defining journey owes a debt to The Odyssey. This imaginative program uses the poem's division into groupings of books as a framework to allow Dr. Tom Winnifrith, of Warwick University; Dr. Douglas Cairns, of Leeds University; and Ken Dowden, senior lecturer at Birmingham University, to analyze the oral tradition and key elements of the story line. Readings and dramatizations from The Odyssey enhance the discussion of recurrent themes, characterization, relationships, morals, and the cumulative effect of the ten-year journey in shaping and seasoning Odysseus. (31 minutes)
The Odyssey by Homer; Emily Wilson (Translator)
Call Number: PA4025.A5W56 2018
The first great adventure story in the Western canon, The Odyssey is a poem about violence and the aftermath of war; about wealth, poverty, and power; about marriage and family; about travelers, hospitality, and the yearning for home.In this fresh, authoritative version--the first English translation of The Odyssey by a woman--this stirring tale of shipwrecks, monsters, and magic comes alive in an entirely new way. Written in iambic pentameter verse and a vivid, contemporary idiom, this engrossing translation matches the number of lines in the Greek original, thus striding at Homer's sprightly pace and singing with a voice that echoes Homer's music.Wilson's Odyssey captures the beauty and enchantment of this ancient poem as well as the suspense and drama of its narrative. Its characters are unforgettable, from the cunning goddess Athena, whose interventions guide and protect the hero, to the awkward teenage son, Telemachus, who struggles to achieve adulthood and find his father; from the cautious, clever, and miserable Penelope, who somehow keeps clamoring suitors at bay during her husband's long absence, to the "complicated" hero himself, a man of many disguises, many tricks, and many moods, who emerges in this translation as a more fully rounded human being than ever before.A fascinating introduction provides an informative overview of the Bronze Age milieu that produced the epic, the major themes of the poem, the controversies about its origins, and the unparalleled scope of its impact and influence. Maps drawn especially for this volume, a pronunciation glossary, and extensive notes and summaries of each book make this an Odyssey that will be treasured by a new generation of scholars, students, and general readers alike.
Overview, Background, & Analysis
"Arthurian Romance" in Arts and Humanities Through the Eras by Edward I. Bleiberg, et al.
Profiling milestones in Medieval Europe from 814 to 1450 dealing with the Arthurian legend.
Frustrated readers and conventional decapitation in 'Sir Gawain and the Green Knight.'
In this essay, Moll compares and contrasts the layers of Sir Gawain's image in medieval romance.
In the Footsteps of Sir Gawain and the Green Knight by BBC
Written around 1400 in Middle English by an unknown hand, Sir Gawain and the Green Knight is a mysterious poem about an uncanny event that takes place in the legendary realm of King Arthur. In this program, renowned Gawain translator Simon Armitage seeks a richer understanding of the poem by walking the fading trail that ends at the Green Chapel, the climax point of the famously alliterative epic that is equal parts adventure story, supernatural tale, steamy romance, parable, and tribute to nature. Enthralling! Readings and commentary by Armitage are interwoven throughout the narrative.
Sir Gawain and the Green Knight: an introduction
The Camelot Project
Collections include an extensive selection of full-text sources, image and character galleries, as well as sections concerning places, and creatures mentions in Arthurian literature. Sponsored by the University of Rochester.
Sir Gawain and the Green Knight by Helen Cooper (Editor); Keith Harrison (Translator)
Sir Gawain and The Green Knight, with its intricate plot of enchantment and betrayal is probably the most skilfully told story in the whole of the English Arthurian cycle. Originating from the north-west midlands of England, it is based on two separate and very ancient Celtic motifs of the Beheading and the Exchange of Winnings, brought together by the anonymous 14th century author. Acclaimed poet Keith Harrison's new translation uses a modern alliterative pattern which subtly echoes the music of the original at the same time as it strives for fidelity. This is the most generously annotated edition available, complete with a detailed introduction which situates the work in the context of Arthurian Romance as well as analyzing its poetics and narrative structure.
The Song of Roland by University of Colorado
Compiled in the 11th century, The Song of Roland is perhaps the world's most famous portrait of early European chivalry, piousness, and militarism. This beautifully produced program offers an abridged English version of the battlefield epic, combining richly textured medieval and Renaissance art images with scholarly summaries and interpretations of the work's major sections. Acknowledging the poem's historical inaccuracies, the video nevertheless underscores its importance for later European listeners: specifically, as a rallying cry mobilizing Christian forces to embark on the Crusades.
The Song of Roland by Glyn S. Burgess (Introduction by, Notes by, Translator)
Call Number: PQ1521.E5 B78 1990
On 15 August 778, Charlemagne's army was returning from a successful expedition against Saracen Spain when its rearguard was ambushed in a remote Pyrenean pass. Out of this skirmish arose a stirring tale of war, which was recorded in the oldest extant epic poem in French. The Song of Roland, written by an unknown poet, tells of Charlemagne's warrior nephew, Lord of the Breton Marches, who valiantly leads his men into battle against the Saracens, but dies in the massacre, defiant to the end. In majestic verses, the battle becomes a symbolic struggle between Christianity and paganism, while Roland's last stand is the ultimate expression of honour and feudal values of twelfth-century France. For more than seventy years, Penguin has been the leading publisher of classic literature in the English-speaking world. With more than 1,700 titles, Penguin Classics represents a global bookshelf of the best works throughout history and across genres and disciplines. Readers trust the series to provide authoritative texts enhanced by introductions and notes by distinguished scholars and contemporary authors, as well as up-to-date translations by award-winning translators.
<< Previous: Epics & Folklore
Next: Graphic Novels, Comics Art, & Manga >>
Last Updated: Mar 20, 2019 8:18 PM
URL: https://libguides.southflorida.edu/literature
Tags: authors, children's literature, creative writing, epics, folklore, graphic novels, literature, subject guide, world literature


Rodriguez was effective with quick throws to the outside. The Panthers were shut down in the run game early but had success in the air with Rodriguez connecting with wide receiver Ivan Sanchez. The Panthers scored on a 2-yard run closing the gap to 14-6 YHS. It was as close as the Panthers would get.
The Badgers exploded in the second quarter scoring 18 unanswered points. Harper went to work behind solid blocking from the Badger offensive line. Harper scored on touchdown runs of 5 and 65 yards. Eames got his second pick and returned it 45 yards for his second touchdown. Just like that YHS blew open a close contest. Rodriguez connected with Sanchez on a 53-yard touchdown pass at the end of the second quarter. The Badgers went into halftime up 32-13.
Parlier continued to battle through the air in the third quarter. The Panthers scored on a 15-yard pass from Rodriguez to Sanchez and later on a 6-yard run. The Panthers were now in striking distance. After a Mansfield 1-yard score the Badgers held a 38-26 lead going into the fourth quarter. The Badgers sustained long drives in the fourth however with Harper scoring twice to seal the win.
The Badgers pounded out 265 yards on the ground. Harper ran for his second straight 100-yard-plus game. Harper's 32 points is second all-time at YHS for points scored in a game. Harper scored touchdowns on three straight plays in the second half. He also scored on a two-point conversion. Kyler Schaeffer had seven carries for 51 yards.
With injuries to receivers Paul Antonis and Steven Baker, Eames was the top target catching six passes for 57 yards. Antonis caught 2 passes for 57 yards before his injury in the third quarter.
Quarterback Tyson Mansfield was an efficient 9 of 16 for 109 yards but had two interceptions, one on a tip.
The Badger defense allowed 34 points after shutting out Riverdale last week. The Panthers had no ground game as YHS controlled the line of scrimmage. But Rodriguez was effective keeping the YHS secondary busy.
The Mustangs of Minarets are next. Yosemite travels to O'Neals Friday night Aug. 31. (Game times: JV at 5 p.m. and Varsity at 7 p.m.) It is the first of a number of rivalry games this season for both Minarets and YHS. The game will be the biggest test for both teams in this early season.
This is a young rivalry. What makes it special is most players grew up playing with or against each other in youth football. Many players are good friends.
"I know this game is special to players, fans, and the community," Minarets coach Becher Marr said. "Rivalry games are great. For us, we treat each game the same. We will have a good two weeks to prepare. It will be a fun game to watch for sure, just like last year." Minarets is coming off a bye week.
Yosemite defeated Minarets 27-14 last year at YHS. The Badgers went 9-0 in the regular season in 2017.
The Mustangs lost their home opener 15-13 against Mariposa. Even though the Mustangs had five turnovers and 10 penalties they were in a position to win on their final drive.
Minarets and YHS have similar weapons. Both can move the ball well running or passing. Minarets has a strong run game featuring Tyson Ellis who had 118 yards rushing against Mariposa. The Mustangs feature receivers Preston Conti (1,050 receiving yards and 11 TDs in 2017) and Zach Redman. Conti, a Rivals.com West Coast Top 20 Receiver, was double- and triple-teamed against Mariposa. Redman stepped up and had a solid game with 84 yards and a touchdown.
Both lines are big and strong. Both teams will lay the wood on defense. That's what happens in rivalries.
At quarterback it will be first-year varsity starter Marty Urroz of Minarets against the experienced Tyson Mansfield of YHS. Urroz is talented, has a good arm, and is capable on his feet. He has a very athletic receiving corps. Ellis can be a big threat out of the backfield.
Mansfield led YHS to the playoffs last season engineering three game-winning drives along the way. Mansfield has command of the Badger offense and makes few mistakes. It could be the difference.
There was only one touchdown scored in the JV game between YHS and Parlier. It was a 1-yard run by Garrett McMechan in the second quarter. In a defensive battle, YHS (1-1, 0-0) prevailed 7-0 over Parlier (0-2, 0-0).
McMechan led YHS with 85 yards rushing. Yosmar Wellborn led YHS with three receptions for 40 yards. Quarterback Rodney Von Wagner was nearly perfect completing 4 of 5 passes for 61 yards. He also rushed for 24 yards.


How Do I Use Self Tapping Screws?
Arguably, the image of a self tapping fastener is one of the most archetypal images of a screw. Many will envision the definitive 'screw' as a countersunk screw, usually with a Phillips drive and a sharpened point. A quick Google search for the term 'screws' shows an overwhelming bias towards self tapping fasteners, despite the innumerable permutations available. Despite its apparent popularity, 'How do I use a self-tapping screw?' is still a very common question - some of the basics will be covered within this article.
What is The Difference Between Self Tapping and Self Drilling Screws?
Tapping is the act of creating a thread. Tapping is not the act of creating a hole. In soft materials, such as wood or plastic, there is some overlap in these processes, as a self tapping tip is usually sufficient to create the hole required. However, with metals or certain particularly hard woods, a pilot hole must be drilled before a thread can be tapped.
An important consideration in any self tapping application is to select the ideal drive type for the given situation and the tooling available. Common choices include slotted or Phillips drives - or the Pozi drive, which was specifically invented for self tapping applications. For more information see our article on the advantages of the Pozi drive. Deeper socket drives are also regularly used in high-torque applications.
When installing a self tapping screw, the screw must be properly aligned to ensure that it is driven into the target housing as the correct angle. This is particularly important if a self tapping screw is expected to cut its own hole, as there is no pilot hole to guide the fastener. Many methods exist for ensuring perpendicular holes, from improvised jigs to high-precision guidance tooling.
Many factors go into the selection of an ideal pilot hole, including some degree of preference in the amount of thread engagement required. Factors such as fastener material, housing material, hole depth, and even temperature must be considered. For these reasons, it is near impossible to guarantee a recommended pilot hole size for your specific application. As a rough guide, a pilot hole should be between the minor diameter and major diameter of the screw thread, but will always vary dependent on external factors. The table below gives several recommended hole sizes, but should be used as a guide only.
*Figures given for stainless steel fasteners used in unhardened metals such as mild steel, brass, aluminium etc. Use as a guide only.
As mentioned above, when used with sufficiently soft materials, a self tapping screw can be used to create and tap its own hole. However, a pilot hole is often recommended, particularly in hardwoods, to prevent splitting, which is caused by stresses within the wood. Wood screws are designed with very coarse threads to reduce stresses within wooden housings.
Certain types of self-tapping screw have been specially designed for use with plastics. While regular self tapping screws are suitable for use with most plastics, Plastite screws feature more pronounced, sharper threads, which increase resistance to pull-out and stripping within low-density plastics.
When used with metal, Self-tapping screws should always be installed into pre-drilled holes. Stainless steel screws are relatively soft when compared to hardened steel, and are generally recommended for use with softer metals, such as Aluminium.