/// <summary> /// Extracts the inputted child from this container, but keeps it alive for insertion into another /// </summary> /// <param name="childToExtract">The child we wish to extract from this container</param> public T ExtractChild <T>(T childToExtract) where T : BaseObject { DebugUtils.AssertNotNull(childToExtract); childToExtract.Parent = null; return(Children.ExtractChild(childToExtract)); }
/// <summary> /// A wrapper for loading content directly using the ContentManager. /// Should only be used as a last resort. /// </summary> /// <typeparam name="T">The type of content to load</typeparam> /// <param name="path">The full path of the object from the ContentManager directory e.g. Sprites\\UI\\Cursor</param> /// <param name="extension">The extension of the file we are trying to load - used for error checking</param> /// <returns>The loaded content</returns> private static T LoadAssetFromDisc <T>(string path, bool createIfDoesNotExist = false) { ContentManager content = ScreenManager.Instance.Content; T asset = default(T); // Because File.Exists relies on extensions and we do not use extensions, we cannot do a test here. // We use try catch here instead. // Ouch - I know, but there's no real nice workaround, unless we can check without extensions try { asset = content.Load <T>(path); } catch { if (createIfDoesNotExist) { asset = (T)Activator.CreateInstance(typeof(T)); } else { asset = default(T); } } DebugUtils.AssertNotNull(asset); return(asset); }
/// <summary> /// A function to remove a child /// </summary> /// <param name="childToRemove">The child we wish to remove</param> public void RemoveChild(BaseObject childToRemove) { DebugUtils.AssertNotNull(childToRemove); // This function will set IsAlive to false so that the object gets cleaned up next Update loop Children.RemoveChild(childToRemove); }
/// <summary> /// Handles the behaviour we want from this UI - to move with the mouse when it is pressed over it, and stop when released. /// Then updates the value if needs be. /// </summary> /// <param name="elapsedGameTime"></param> /// <param name="mousePosition"></param> public override void HandleInput(float elapsedGameTime, Vector2 mousePosition) { base.HandleInput(elapsedGameTime, mousePosition); DebugUtils.AssertNotNull(SliderHandle.Collider); if (SliderHandle.Collider.IsSelected) { float sliderBarHalfWidth = Size.X * 0.5f; float newX = MathHelper.Clamp(mousePosition.X - WorldPosition.X, -sliderBarHalfWidth, sliderBarHalfWidth); SliderHandle.LocalPosition = new Vector2(newX, 0); // Calculate our new value float multiplier = (newX + sliderBarHalfWidth) / (2 * sliderBarHalfWidth); Debug.Assert(multiplier >= 0 && multiplier <= 1); CurrentValue = (1 - multiplier) * MinValue + multiplier * MaxValue; // Update our value label text ValueLabel.Text = CurrentValue.ToString(); // We do asserts rather than actual clamping, because if these asserts are false the slider is behaving incorrectly Debug.Assert(CurrentValue >= MinValue); Debug.Assert(CurrentValue <= MaxValue); if (OnValueChanged != null) { OnValueChanged(this); } } }
/// <summary> /// Set the base object to the max opacity /// </summary> public override void Begin() { base.Begin(); DebugUtils.AssertNotNull(AttachedBaseObject); AttachedBaseObject.Opacity = MaxOpacity; }
/// <summary> /// Extracts the inputted child from this container, but keeps it alive for insertion into another /// </summary> /// <param name="childToExtract">The child we wish to extract from this container</param> public K ExtractChild <K>(K childToExtract) where K : T { DebugUtils.AssertNotNull(childToExtract); ObjectsToRemove.Add(childToExtract); return(childToExtract); }
/// <summary> /// Checks each object in the inputted ObjectManager to determine whether it should be drawn this frame. /// </summary> /// <param name="objectManager"></param> /// <param name="screenSpace"></param> public void CheckVisibility <T>(ObjectManager <T> objectManager, bool screenSpace) where T : BaseObject { Rectangle rectangleToUse = screenSpace ? ViewportRectangleScreenSpace : ViewportRectangleGameSpace; Vector2 centre = rectangleToUse.Center.ToVector2(); foreach (BaseObject baseObject in objectManager) { // If our object's visibility is driven by another object we do not need to perform visibility checks if (baseObject.ShouldDraw) { continue; } if (baseObject.UsesCollider) { DebugUtils.AssertNotNull(baseObject.Collider); baseObject.ShouldDraw = baseObject.Collider.CheckIntersects(rectangleToUse); } else { // Crude circle check, can definitely be improved upon float x = rectangleToUse.Width + baseObject.Size.X; float y = rectangleToUse.Height + baseObject.Size.Y; baseObject.ShouldDraw = (centre - baseObject.WorldPosition).LengthSquared() <= x * x + y * y; } } }
/// <summary> /// A utility function which wraps the extraction of this from it's current owner and the insertion into the new one. /// Should only be called if it's parent is already set - otherwise use AddChild. /// The second parameter is a flag we can pass to prevent us from calling newParent.AddChild - this is in case we do not want to call custom implementation in an AddChild function. /// This does mean that if the object is not reinserted manually elsewhere, it will be left hanging around, but not being updated. /// </summary> /// <param name="newParent"></param> public void ReparentTo(BaseObject newParent, bool moveToNewParentsChildren = true) { // Extract ourselves from our parent DebugUtils.AssertNotNull(Parent); // We are reparenting to ourselves, so no need to go through this whole process of extraction and addition again if (Parent == newParent) { return; } Parent.ExtractChild(this); // Assume this has been loaded and initialised and insert it into the new parent's Children (if not null) if (newParent != null) { if (moveToNewParentsChildren) { newParent.AddChild(this); } else { // We do not want to call add child, but rather do a shallow parent set Parent = newParent; } } }
/// <summary> /// Sets up the size to preserve the texture aspect ratio /// </summary> public override void Initialise() { // Check to see whether we should Initialise CheckShouldInitialise(); // Texture cannot be null DebugUtils.AssertNotNull(Texture); // If we are preserving aspect ratio, recalculate the size if (PreservesAspectRatio) { float aspectRatio = Texture.Bounds.Height / (float)Texture.Bounds.Width; Debug.Assert(aspectRatio > 0); if (aspectRatio < 1) { Size = new Vector2(Size.X, Size.X * aspectRatio); } else { Size = new Vector2(Size.Y / aspectRatio, Size.Y); } } base.Initialise(); }
/// <summary> /// Reads the element value of the xml element the inputted reader is currently on as the inputted type. /// This method may call itself recursively for a nested list for example. /// Finally, returns the successfully deserialized object. /// Moves the nodereader past the end tag so do not need to do ReadEndElement after calling this function. /// </summary> /// <param name="nodeReader"></param> /// <param name="typeOfElement"></param> /// <returns></returns> private static object ReadElementValue(XmlReader nodeReader, Type typeOfElement) { // Set the value to the default value of the type - for value types we create an instance, for reference types we use null object value = null; try { Activator.CreateInstance(typeOfElement); } catch { } if (nodeReader.NodeType == XmlNodeType.Text) { // Read the element's content and convert it to the type of the property we are setting value = nodeReader.ReadContentAs(typeOfElement, null); } else if (nodeReader.NodeType == XmlNodeType.Element) { int startingDepth = nodeReader.Depth; // Currently only nesting Elements inside other elements is supported // This will be called if we are deserializing a list or custom data type Debug.Assert(nodeReader.NodeType == XmlNodeType.Element); if (IsListType(typeOfElement)) { value = Activator.CreateInstance(typeOfElement); // Get the add method so we can add objects to the list at runtime MethodInfo addMethod = value.GetType().GetRuntimeMethods().First(x => x.Name == "Add"); DebugUtils.AssertNotNull(addMethod); // Keep reading whilst we still have nested elements while (nodeReader.Depth >= startingDepth) { Debug.Assert(typeOfElement.GenericTypeArguments.Length == 1); Type listGenericArgumentType = typeOfElement.GenericTypeArguments[0]; object nestedValue = nodeReader.ReadElementContentAs(listGenericArgumentType, null); addMethod.Invoke(value, new object[] { nestedValue }); } } else { // We are trying to read a class value = ReadType <object>(nodeReader, typeOfElement); } } else if (nodeReader.NodeType == XmlNodeType.EndElement) { // This can happen if we have something like an empty string e.g. <String></String> // Noop } // Finally read the end tag nodeReader.ReadEndElement(); return(value); }
/// <summary> /// Returns the most recent child we added which is castable to the inputted type and satisfies the inputted condition. /// Shouldn't really be called unless we have children /// </summary> /// <returns>The most recent child we added</returns> public K LastChild <K>(Predicate <K> condition) where K : T { K lastChildOfType = ActiveObjects.FindLast(x => x is K && condition(x as K)) as K; DebugUtils.AssertNotNull(lastChildOfType); return(lastChildOfType); }
/// <summary> /// Returns the most recent child we added which is castable to the inputted type. /// Shouldn't really be called unless we have children /// </summary> /// <returns>The most recent child we added</returns> public K LastChild <K>() where K : T { K lastChildOfType = ActiveObjects.FindLast(x => x is K) as K; DebugUtils.AssertNotNull(lastChildOfType); return(lastChildOfType); }
/// <summary> /// A function to remove and kill a child /// </summary> /// <param name="childToRemove">The child we wish to remove</param> public void RemoveChild(T childToRemove) { DebugUtils.AssertNotNull(childToRemove); Debug.Assert(Exists(x => x == childToRemove)); // This function will set IsAlive to false so that the object gets cleaned up next Update loop childToRemove.Die(); }
public ClickableImage(Vector2 size, Anchor anchor, int depth, string textureAsset) : base(size, anchor, depth, textureAsset) { UsesCollider = true; ClickableModule = AddModule(new ClickableObjectModule()); DebugUtils.AssertNotNull(ClickableModule); }
public ClickableImage(Vector2 size, Vector2 localPosition, string textureAsset) : base(size, localPosition, textureAsset) { UsesCollider = true; ClickableModule = AddModule(new ClickableObjectModule()); DebugUtils.AssertNotNull(ClickableModule); }
/// <summary> /// Utility function wrapping around ReadType<> where we find the type using the assembly and typeName /// </summary> /// <param name="nodeReader"></param> /// <param name="typeName"></param> private static T ReadType <T>(XmlReader nodeReader, Assembly assembly, string typeName) { Type typeToLoad = assembly.ExportedTypes.FirstOrDefault(x => x.Name == typeName); DebugUtils.AssertNotNull(typeToLoad, "Type " + typeName + " specified for data file could not be loaded"); return(ReadType <T>(nodeReader, typeToLoad)); }
/// <summary> /// Returns the most recent child we added and is buffered to be inserted into ActiveObjects which is castable to the inputted type. /// Shouldn't really be called unless we have children waiting to be added. /// </summary> /// <returns>The most recent child we added</returns> public K LastChildToBeAdded <K>() where K : T { K lastChildOfType = ObjectsToAdd.FindLast(x => x is K) as K; DebugUtils.AssertNotNull(lastChildOfType); return(lastChildOfType); }
/// <summary> /// A callback for our loading thread to load all our game's assets. /// </summary> private void LoadAllAssetsCallback() { ContentManager content = ScreenManager.Instance.Content; DebugUtils.AssertNotNull(content); DebugUtils.AssertNotNull(LoadAssets); // LoadAssets should REALLY PROBABLY not be null, unless we decide to not load ANYTHING LoadAssets(content); TransitionCallback(); }
/// <summary> /// Loads the effect for the lighting. /// </summary> public override void LoadContent() { CheckShouldLoad(); LightEffect = AssetManager.GetEffect(defaultLightEffect); DebugUtils.AssertNotNull(LightEffect); base.LoadContent(); }
/// <summary> /// Loads the ToolTip object /// </summary> public override void LoadContent() { CheckShouldLoad(); DebugUtils.AssertNotNull(ToolTip); ToolTip.LoadContent(); base.LoadContent(); }
/// <summary> /// Syncs our button's value with our options is full screen option /// </summary> /// <param name="baseObject"></param> private void SyncOptionsIsFullScreen(BaseObject baseObject) { Debug.Assert(baseObject is Button); Button button = baseObject as Button; DebugUtils.AssertNotNull(button); OptionsManager.IsFullScreen = !OptionsManager.IsFullScreen; button.Label.Text = OptionsManager.IsFullScreen.ToString(); }
/// <summary> /// A function which will be used to add a child and sets it's parent to this /// </summary> /// <typeparam name="K">The type of the child</typeparam> /// <param name="childToAdd">The child itself</param> /// <param name="load">A flag to indicate whether we wish to call LoadContent on the child</param> /// <param name="initialise">A flag to indicate whether we wish to call Initialise on the child</param> /// <returns></returns> public virtual K AddChild <K>(K childToAdd, bool load = false, bool initialise = false) where K : BaseObject { DebugUtils.AssertNotNull(childToAdd); DebugUtils.AssertNull(childToAdd.Parent); // Set the parent to be this childToAdd.Parent = this; return(Children.AddChild(childToAdd, load, initialise)); }
public Particle(Vector2 startSize, Vector2 localPosition, AnimationData animationData, float lifeTime) : base(localPosition, "") { UsesCollider = false; LerpAmount = 0; StartColour = Colour; StartSize = startSize; DebugUtils.AssertNotNull(animationData); AnimationData = animationData; }
/// <summary> /// Calculates the source rectangle from the sprite sheet we should use based on the dimensions and current frame. /// </summary> private void CalculateSourceRectangle() { int currentRow = CurrentFrame / Frames.X; int currentColumn = CurrentFrame % Frames.X; Debug.Assert(currentColumn < Frames.X); Debug.Assert(currentRow < Frames.Y); DebugUtils.AssertNotNull(AttachedBaseObject); AttachedBaseObject.SourceRectangle = new Rectangle(currentColumn * FrameDimensions.X, currentRow * FrameDimensions.Y, FrameDimensions.X, FrameDimensions.Y); }
/// <summary> /// Fixup UI positions /// </summary> public override void Begin() { base.Begin(); DebugUtils.AssertNotNull(FullScreenLabel); DebugUtils.AssertNotNull(FullScreenLabel.Parent); float padding = 5; FullScreenLabel.LocalPosition = new Vector2(-(FullScreenLabel.Parent.Size.X + FullScreenLabel.Size.X) * 0.5f - padding, 0); }
/// <summary> /// Check that the texture has been loaded by doing a get call /// </summary> public override void LoadContent() { // Check to see whether we should load CheckShouldLoad(); DebugUtils.AssertNotNull(Texture); Children.LoadContent(); Modules.LoadContent(); base.LoadContent(); }
/// <summary> /// Checks to see if this object is right clicked, and if so, kills the object. /// </summary> /// <param name="elapsedGameTime"></param> /// <param name="mousePosition"></param> public override void HandleInput(float elapsedGameTime, Vector2 mousePosition) { base.HandleInput(elapsedGameTime, mousePosition); DebugUtils.AssertNotNull(Collider); if (GameMouse.Instance.IsClicked(MouseButton.kRightButton) && Collider.CheckIntersects(GameMouse.Instance.InGameWorldPosition)) { Die(); } }
/// <summary> /// Loads our button textures /// </summary> public override void LoadContent() { CheckShouldLoad(); HighlightedTexture = AssetManager.GetSprite(_highlightedTextureAsset); DebugUtils.AssertNotNull(HighlightedTexture); base.LoadContent(); DebugUtils.AssertNotNull(Texture); DefaultTexture = Texture; }
/// <summary> /// Get a pre-loaded music file /// </summary> /// <param name="path">The full path of the SoundEffect, e.g. "Menu\\Emotional"</param> /// <returns></returns> public static Song GetMusic(string path) { Song song; if (!Songs.TryGetValue(path, out song)) { song = LoadAssetFromDisc <Song>(Path.Combine(MusicPath, path)); } DebugUtils.AssertNotNull(song); return(song); }
public static void SaveAssets() { DebugUtils.AssertNotNull(AssetManager.OptionsPath); OptionsData options = new OptionsData(); options.IsFullScreen = IsFullScreen; options.MusicVolume = MusicVolume; options.SFXVolume = SFXVolume; AssetManager.SaveData(options, AssetManager.OptionsPath); }