adding objects programmatically to powerpoint slides forcing all objects animation - c#

I am adding some objects to a PowerPoint slide on the fly along with some animations. Problem is when I add any object after adding the first object then both the previously added object along with current object comes with animation. How do I make my previously added object stay as it is and only the new one come with animation, here is some code that I am using,
private void AddShapeToSlide(int left, int top, int width, int height)
{
Slide slide = GetCurrentSlide();
Shape shape = slide.Shapes.AddShape(MsoAutoShapeType.msoShapeRectangle, left, top, width, height);
ApplyAnimation(slide, shape);
shape.ZOrder(MsoZOrderCmd.msoBringToFront);
_presentation.SlideShowWindow.Activate();
}
private void ApplyAnimation(Slide slide, Shape shape)
{
shape.AnimationSettings.AdvanceMode = PpAdvanceMode.ppAdvanceOnTime;
shape.AnimationSettings.AdvanceTime = 0;
shape.AnimationSettings.Animate = MsoTriState.msoTrue;
shape.AnimationSettings.EntryEffect = GetPowerPointTransition();
Effect effect = slide.TimeLine.MainSequence.FindFirstAnimationFor(shape);
if (effect != null && shape.AnimationSettings.EntryEffect != PpEntryEffect.ppEffectNone)
{
effect.Timing.Duration = 5;
}
}
Any help or idea is of great value. Thanks In Advance.

Related

SkiaSharp Touch Bitmap Image

In the app I'm trying to develop a key part is getting the position of where the user has touched. First I thought of using a tap gesture recognizer but after a quick google search I learned that was useless (See here for an example).
Then I believe I discovered SkiaSharp and after learning how to use it, at least somewhat, I'm still not sure how I get the proper coordinates of a touch. Here are sections of the code in my project that are relevant to the problem.
Canvas Touch Function
private void canvasView_Touch(object sender, SKTouchEventArgs e)
{
// Only carry on with this function if the image is already on screen.
if(m_isImageDisplayed)
{
// Use switch to get what type of action occurred.
switch (e.ActionType)
{
case SKTouchAction.Pressed:
TouchImage(e.Location);
// Update simply tries to draw a small square using double for loops.
m_editedBm = Update(sender);
// Refresh screen.
(sender as SKCanvasView).InvalidateSurface();
break;
default:
break;
}
}
}
Touch Image
private void TouchImage(SKPoint point)
{
// Is the point in range of the canvas?
if(point.X >= m_x && point.X <= (m_editedCanvasSize.Width + m_x) &&
point.Y >= m_y && point.Y <= (m_editedCanvasSize.Height + m_y))
{
// Save the point for later and set the boolean to true so the algorithm can begin.
m_clickPoint = point;
m_updateAlgorithm = true;
}
}
Here I'm just seeing or TRYING to see if the point clicked was in range of the image and I made a different SkSize variable to help. Ignore the boolean, not that important.
Update function (function that attempts to draw ON the point pressed so it's the most important)
public SKBitmap Update(object sender)
{
// Create the default test color to replace current pixel colors in the bitmap.
SKColor color = new SKColor(255, 255, 255);
// Create a new surface with the current bitmap.
using (var surface = new SKCanvas(m_editedBm))
{
/* According to this: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/paths/finger-paint ,
the points I have to start are in Xamarin forms coordinates, but I need to translate them to SkiaSharp coordinates which are in
pixels. */
Point pt = new Point((double)m_touchPoint.X, (double)m_touchPoint.Y);
SKPoint newPoint = ConvertToPixel(pt);
// Loop over the touch point start, then go to a certain value (like x + 100) just to get a "block" that's been altered for pixels.
for (int x = (int)newPoint.X; x < (int)newPoint.X + 200.0f; ++x)
{
for (int y = (int)newPoint.Y; y < (int)newPoint.Y + 200.0f; ++y)
{
// According to the x and y, change the color.
m_editedBm.SetPixel(x, y, color);
}
}
return m_editedBm;
}
}
Here I'm THINKING that it'll start, you know, at the coordinate I pressed (and these coordinates have been confirmed to be within the range of the image thanks to the function "TouchImage". And when it does get the correct coordinates (or at least it SHOULD of done that) the square will be drawn one "line" at a time. I have a game programming background so this kind of sounds simple but I can't believe I didn't get this right the first time.
Also I have another function, it MIGHT prove worthwhile because the original image is rotated and then put on screen. Why? Well by default the image, after taking the picture, and then displayed, is rotated to the left. I had no idea why but I corrected it with the following function:
// Just rotate the image because for some reason it's titled 90 degrees to the left.
public static SKBitmap Rotate()
{
using (var bitmap = m_bm)
{
// The new ones width IS the old ones height.
var rotated = new SKBitmap(bitmap.Height, bitmap.Width);
using (var surface = new SKCanvas(rotated))
{
surface.Translate(rotated.Width, 0.0f);
surface.RotateDegrees(90);
surface.DrawBitmap(bitmap, 0, 0);
}
return rotated;
}
}
I'll keep reading and looking up stuff on what I'm doing wrong, but if any help is given I'm grateful.

Relocate children in grid

I'm trying to realize a chess game in C# with WPF. By now I visualized the chess grid and the figures in it. My .xaml file contains just a grid (named "playground") which is 8x8. The initializing in the .xaml.cs file looks like the following:
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 8; y++)
{
Border border = new Border();
if (y % 2 == (x % 2 == 0 ? 0 : 1))
{ // Chess like look
border.Background = black; //black is a static SolidColorBrush
}
// a ChessTile is an Image which can be a Figure or an EmptyTile
// omitted code... evaluate whether what figure the tile is or empty
ChessTile tile;
Grid.SetColumn(border, x);
Grid.SetRow(border, y);
border.HorizontalAlignment = HorizontalAlignment.Stretch;
border.VerticalAlignment = VerticalAlignment.Stretch;
if (tile is Figure)
{
// Set Event to border so the user is able to click outside the image
border.MouseDown += ClickFigure;
}
border.Child = tile; // Set tile as Child
playground.Children.Add(border); // Add border to Child
}
}
After initializing I want to move a chess figure to another Column and or Row in the grid. Currently I am evaluating in ClickFigure on which empty tile the figure is able to move to, then adding a new Handler to these empty tiles and moving my Figures there. I'm calling tile.Move(otherTile) in the Handler:
(from ChessTile.cs)
public Vector Coordinates
{
get
{
return position; //private Vector
}
private set
{
position = value;
Grid.SetRow(this, (int)position.X); //relocate this (ChessTile)
Grid.SetColumn(this, (int)position.Y);
}
}
public void Move(ChessTile other)
{
Vector temp = position;
Coordinates = other.position; //relocating both tiles through properties
other.Coordinates = temp;
}
The problem now is that the grid does not do anything at all. I searched for some method to update/repaint the grid manually but I didn't find anything. I also tried to remove the child first and then to add it again but that gave me an error saying that the child was already bound to an UIElement and that I would have to seperate it first.
Do you have any idea what I am doing wrong?
You need to change the row and column on the original Border placed inside the Grid.
In your setup code, you set column and row on a border object:
Grid.SetColumn(border, x);
Grid.SetRow(border, y);
But then in your Coordinates property, you're setting the column and row on this.
Grid.SetRow(this, (int)position.X); //relocate this (ChessTile)
Grid.SetColumn(this, (int)position.Y);
Assuming this is a custom class you've written, then you need to make sure it has a reference to the original Border and change your Coordinate setter to:
Grid.SetRow(border, (int)position.X); //relocate the border!
Grid.SetColumn(border, (int)position.Y);
Notice the change from this => border.

Unity3D - Displaying a message at the border of the screen

I want to display a kind of banner everytime the player enters a new location. This should be at the very left border of the screen. My problem is that my current solution behaves inconsistently across resolutions. On higher resolutions the banner is positioned further to the right than needed.
I also use a piece of code to properly position the text every time it is displayed.
public class AreaName : MonoBehaviour
{
private static AreaName instance;
void Start ()
{
if (instance)
Destroy(this);
else
instance = this;
BannerBase = transform.FindChild("BannerBase").GetComponent<Image>();
NameDisplay = BannerBase.transform.FindChild("BannerText").GetComponent<Text>();
}
private Image BannerBase;
private Text NameDisplay;
public static void Display (string areatitle)
{
int width = TextWidth(instance.NameDisplay, areatitle);
instance.BannerBase.rectTransform.position = new Vector3(-305 + width, instance.BannerBase.transform.position.y, 0);
instance.NameDisplay.text = areatitle;
print(width);
}
private static int TextWidth (Text obj, string text)
{
int totalLength = 0;
Font myFont = obj.font; //chatText is my Text component
CharacterInfo characterInfo = new CharacterInfo();
char[] arr = text.ToCharArray();
foreach (char c in arr)
{
myFont.GetCharacterInfo(c, out characterInfo, obj.fontSize);
totalLength += characterInfo.advance;
}
return totalLength;
}
}
Are there any simple errors that I am overseeing? Or am I just understanding the Unity UI system wrong?
You shouldn't need to code nothing to do that.
You have put your banner at the lower left corner of the screen, with a (0,0) pivot, that's all right, but, why is it positioned at x: -320?
If you put your banner at -320 for some reason, at native resolution it probably will work as expected, but if you have activated the Canvas Resizer, at other resolutions it will be moved since is not positioned at the corner at all.

Embed Any Control with UltraControlContainerEditor does not work for Image column

I want to display a picture in another scaling mode in an UltraGridCell. The mode should scale the image to the cell height and clip the rest of the image from the right to fit into the cell. This is easy if I could just draw it myself as the EmbeddableImageRenderer does not allow me to set its scaling behaviour (I am not talking about MaintainAspectRatio as I still want to maintain the aspect ratio).
I tried it with the tutorial to embed any control in a cell. And it is working fine with the given example of a TrackBar (and in my tiny testing project also with a ProgressBar as RendererControl). But it appears not to work with columns that are displaying images.
As a DataSource I have a list of my own class with an Image property which is displayed in the grid. As Editor-/RendererControl I set two regular PictureBoxes.
Any suggestions to solve the main problem of scaling the image or to set any control to the picture column (that would then deal with the scaling)?
I can't see any reason why the UltraControlContainerEditor shouldn't work with an image column, provided that the control you are using has a property that takes an Image and that you specify the correct PropertyName on the editor. But that's probably not the most efficient approach, anyway.
A better approach would be to use a DrawFilter to draw the image yourself.
public class ImageScalingDrawFilter : IUIElementDrawFilter
{
bool IUIElementDrawFilter.DrawElement(DrawPhase drawPhase, ref UIElementDrawParams drawParams)
{
switch (drawPhase)
{
case DrawPhase.BeforeDrawImage:
ImageUIElement imageElement = (ImageUIElement)drawParams.Element;
Image image = imageElement.Image;
int availableHeight = drawParams.Element.RectInsideBorders.Height;
float ratio = (float)availableHeight / (float)image.Height;
float newHeight = image.Height * ratio;
float newWidth = image.Width * ratio;
Rectangle rect = new Rectangle(
imageElement.Rect.X,
imageElement.Rect.Y,
(int)(newWidth),
(int)(newHeight)
);
// Draw the scaled image.
drawParams.Graphics.DrawImage(image, rect);
// This tells the grid not to draw the image (since we've already drawn it).
return true;
}
return false;
}
DrawPhase IUIElementDrawFilter.GetPhasesToFilter(ref UIElementDrawParams drawParams)
{
UIElement element = drawParams.Element;
// Look for an ImageUIElement
if (element is ImageUIElement)
{
// Presumably, we only want to this images in cells
// and not every image in the entire grid, so make sure it's in a cell.
CellUIElement cellElement = element.GetAncestor(typeof(CellUIElement)) as CellUIElement;
if (null != cellElement)
{
// We could also limit this to a particular column or columns.
switch (cellElement.Cell.Column.Key)
{
case "Image":
return DrawPhase.BeforeDrawImage;
}
}
}
return DrawPhase.None;
}
}
You assign the DrawFilter to the grid like so:
private void Form1_Load(object sender, EventArgs e)
{
this.ultraGrid1.DrawFilter = new ImageScalingDrawFilter();
}

TranslateTransform moving elements more than expected

I'm pretty new to WPF (and completely new to animations), so I would imagine there's just something that I'm missing here. I'm in the process of creating a new layout Panel that lays the controls out in a particular way; the details aren't (or shouldn't be) especially important here. What I'd like to do is animate the movement of the elements that I'm managing when I call Arrange on them.
In general, what I do is keep track of the last Rect that I used to Arrange each child element. When ArrangeOverride is called...
If animation is enabled and there is a previous bounding Rect for the element, I Arrange it to the X and Y of that bounding rect with the new Width and Height, then use two DoubleAnimations (one for X and one for Y) to animate it to the X and Y of the new bounds
If animation is disabled or there is no existing bounding Rect for the element, I just Arrange it to the new bounds
When I disable animation, everything renders correctly (which is a good thing). When I enable animation, the elements render in the incorrect locations. If I resize the container, they generally animate themselves back into the correct spot.
Edit for clarification
In general, the error appears to be directly related to the coordinates of the bounds of the control. In other words, if the control is farther to the right to begin with, then the TranslateTransform appears to offset it more than a control that is not as far to the right. The same goes for up/down. Again, resizing seems to correct the problem (in fact, the controls animate themselves into the correct spot, which is frustratingly neat), but only if the entire set of controls is visible in the new size.
This is an abbreviated version of the class:
public class MyPanel : Panel
{
private Dictionary<UIElement, Rect> lastBounds = new Dictionary<UIElement, Rect>();
protected override Size MeasureOverride(Size availableSize)
{
// do all of my measurements here and delete anything from lastBounds that
// isn't on the panel any more. This works fine
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach(UIElement child in Children)
{
Rect newBounds = // get the previously calculated new bounds;
TransformGroup group= child.RenderTransform as TransformGroup;
if (group == null)
{
group = new TransformGroup();
group.Children.Add(new TranslateTransform());
child.RenderTransform = group;
}
Rect lastBounds;
if (!this.lastBounds.TryGetValue(child, out lastBounds))
lastBounds = Rect.Empty;
if (!lastBounds.IsEmpty && EnableAnimation)
{
Rect tempBounds = new Rect(lastBounds.X, lastBounds.Y, newBounds.Width, newBounds.Height);
child.Arrange(tempBounds);
int animationDuration = 300;
DoubleAnimation xAnim = new DoubleAnimation(newBounds.X - lastBounds.X, TimeSpan.FromMilliseconds(animationDuration));
DoubleAnimation yAnim = new DoubleAnimation(newBounds.Y - lastBounds.Y, TimeSpan.FromMilliseconds(animationDuration));
xAnim.AccelerationRatio = yAnim.AccelerationRatio = 0.2;
xAnim.DecelerationRatio = yAnim.DecelerationRatio = 0.7;
TranslateTransform translate = group.Children[0] as TranslateTransform;
translate.BeginAnimation(TranslateTransform.XProperty, xAnim);
translate.BeginAnimation(TranslateTransform.YProperty, yAnim);
}
else
{
child.Arrange(newBounds);
}
}
}
}
You appear to be arranging the children to their old location, then applying a render transform to get them to appear in their new location. This may be an issue because the layout engine might have a problem with you giving it a location that is now outside the parent layout container. You may have better luck always arranging to the new bounds (within the parent element), then applying the render translate animation to move it back to where it really is:
child.Arrange(newBounds);
int animationDuration = 300;
DoubleAnimation xAnim = new DoubleAnimation(lastBounds.X - newBounds.X, 0, TimeSpan.FromMilliseconds(animationDuration));
DoubleAnimation yAnim = new DoubleAnimation(lastBounds.Y - newBounds.Y, 0, TimeSpan.FromMilliseconds(animationDuration));

Categories