I am trying to move a control to another control's position in a sliding effect. The below code works but it is not smooth as expected. I know repaint has to happen for every one pixel move and that has all things to do with this problem. Is there anything I can do to make it smooth?
void changePage(Control currentPage, Control newPage)
{
int curPageStartX = currentPage.Location.X;
newPage.Location = new Point(currentPage.Size.Width + curPageStartX, currentPage.Location.Y);
while (newPage.Location.X > curPageStartX)
{
currentPage.Location = new Point(currentPage.Location.X - 1, currentPage.Location.Y);
newPage.Location = new Point(newPage.Location.X - 1, newPage.Location.Y);
}
}
Related
I have written a method MakeCard() that instantiates a card prefab (having a button) and adds an image to it through the script that uses an array of sprites but the image does not appear in the panel ("Card Pool") under which I'm setting its transform to. I have another method having the same code and it displays the card (with image) in some other panel (works perfectly fine). But the code isn't working for "Card Pool" panel. I am even displaying the index and the name of the card in logs to check if its fine and its fine. pls help!
EDIT: If i change the parent panel of a card from "Hand" to "Card Pool" it displays fine but if i instantiate the card and set its Parent as "Card Pool" it does not display. Hope this info makes any sense!
public void MakeCard(int index)
{
print("Making Card..." + index);
var cardCopy = Instantiate(cardObj, new Vector3(0, 0, 0),
Quaternion.identity);
var newCard = cardCopy.GetComponent<Card>();
newCard.SetFace(myData.shuffleIndex[index]);
print(newCard.GetName());
cardCopy.transform.SetParent(GameObject.Find("Card Pool").transform);
cardCopy.GetComponent<Button>().interactable = false;
}
the other code thats works perfectly fine is:
public void DistributeMyCards()
{
for(int temp = myData.shuffleIndexToStartWith + 12; myData.shuffleIndexToStartWith < temp; myData.shuffleIndexToStartWith++)
{
//localHand.Add(myData.shuffleIndexToStartWith);
Debug.Log("inside for: " + myData.shuffleIndexToStartWith);
var cardCopy = Instantiate(cardObj, new Vector3(0, 0, 0), Quaternion.identity);
var newCard = cardCopy.GetComponent<Card>();
newCard.SetFace(myData.shuffleIndex[myData.shuffleIndexToStartWith]);
cardCopy.transform.SetParent(GameObject.Find("Hand").transform);
var owner = cardCopy.GetComponent<CardOwner>();
owner.photonPlayer = PlayerNetwork.Instance.me;
owner.setCardId(myData.shuffleIndexToStartWith);
if (!PhotonNetwork.isMasterClient)
{
DisableThrowLocal(cardCopy);
}
localHand.Add(cardCopy);
}
}
PS. Its a MP game but I guess that doesn't have anything to do with this problem.
ok so I found the problem. I had to tick the child controls size (height and width) under horizontal layout group component attached to the panel just as the "Hand panel".
I know that there are lot of different threads about horizontal text animation/text scrolling, but unfortunately none of them give smooth scrolling with repeatable text. I have tried double/thickness animation using various WPF controls containing text. Also tried animating with visual brush which gives me by far the most elegant scrolling compared to other approaches (for e.g. playing with Canvas.Left property etc.) but that too goes blur the text, if the text length or the animation speed is too high.
I'm over to a pure DirectX C# implementation using SharpDX library. Should also mention that I'm a beginner with DirectX programming. Here is the code:
public void RunMethod()
{
// Make window active and hide mouse cursor.
window.PointerCursor = null;
window.Activate();
var str = "This is an example of a moving TextLayout object with no snapped pixel boundaries.";
// Infinite loop to prevent the application from exiting.
while (true)
{
// Dispatch all pending events in the queue.
window.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessAllIfPresent);
// Quit if the users presses Escape key.
if (window.GetAsyncKeyState(VirtualKey.Escape) == CoreVirtualKeyStates.Down)
{
return;
}
// Set the Direct2D drawing target.
d2dContext.Target = d2dTarget;
// Clear the target.
d2dContext.BeginDraw();
d2dContext.Clear(Color.CornflowerBlue);
//float layoutXOffset = 0;
float layoutXOffset = layoutX;
// Create the DirectWrite factory objet.
SharpDX.DirectWrite.Factory fontFactory = new SharpDX.DirectWrite.Factory();
// Create a TextFormat object that will use the Segoe UI font with a size of 24 DIPs.
textFormat = new TextFormat(fontFactory, "Verdana", 100.0f);
textLayout2 = new TextLayout(fontFactory, str, textFormat, 2000.0f, 100.0f);
// Draw moving text without pixel snapping, thus giving a smoother movement.
// d2dContext.FillRectangle(new RectangleF(layoutXOffset, 1000, 1000, 100), backgroundBrush);
d2dContext.DrawTextLayout(new Vector2(layoutXOffset, 0), textLayout2, textBrush, DrawTextOptions.NoSnap);
d2dContext.EndDraw();
//var character = str.Substring(0, 1);
//str = str.Remove(0, 1);
//str += character;
layoutX -= 3.0f;
if (layoutX <= -1000)
{
layoutX = 0;
}
// Present the current buffer to the screen.
swapChain.Present(1, PresentFlags.None);
}
}
Basically it creates an endless loop and subtracts the horizontal offset. Here are the challenges: I need repeatable text similar to HTML marquee without any gaps, Would probably need to extend it to multiple monitors.
Please suggest.
I don't know neither how to use DirectX nor sharpdx, but if you want you can consider this solution
I had a similar problem a while ago, but with the text inside a combobox. After a bounty i got what i was looking for. I'm posting the relevant piece of code as an example, but you can check the complete answer here
Basically, whenever you have a textblock/textbox that contain a string that cannot be displayed completely, cause the length exceed the textblock/box lenght you can use this kind of approach. You can define a custom usercontrol derived from the base you need (e.g. SlidingComboBox : Combobox) and define an animation for you storyboard like the following
_animation = new DoubleAnimation()
{
From = 0,
RepeatBehavior = SlideForever ? RepeatBehavior.Forever : new RepeatBehavior(1), //repeat only if slide-forever is true
AutoReverse = SlideForever
};
In my example i wanted this behaviour to be active only when the mouse was on the combobox, so in my custom OnMouse enter i had this piece of code
if (_parent.ActualWidth < textBlock.ActualWidth)
{
_animation.Duration = TimeSpan.FromMilliseconds(((int)textBlock.Text?.Length * 100));
_animation.To = _parent.ActualWidth - textBlock.ActualWidth;
_storyBoard.Begin(textBlock);
}
Where _parent represent the container of the selected item. After a check on the text lenght vs combobox lenght i start the animation and end it at the end of the text to be displayed
Note that in the question i mentioned there are also other soltions. I'm posting the one that worked for me
I am using the built-in search scope with a UISearchDisplayController, and I only have 2 segments.
The problem is that our design needs the buttons to be smaller and centered (it especially looks bad on iPad because the buttons are stretched really wide).
Is there a way to center the UISegmentedControl and make it smaller? I already have the UISegmentedControl pulled out by looping over subViews. And I can set the width of each segment with setWidth:forSegmentAtIndex, but the control is docked to the left. How can I center it?
PS - my app is MonoTouch (Xamarin.iOS), but Obj-C answers are welcome.
Are you adding this via IB or programmatically? In IB, I had to turn off "Autoresize Subviews" and do the resizing of the control dynamically via code. I put the controls I needed to resize into a view that I could bind to then center my control within that view. Here's a sample. I had 2 buttons that I put side-by-side in landscape mode, but it should give you an idea.
// get the current sizes of the things we are moving
CGRect saveRect = self.viewButtons.frame; // the enclosing view
CGRect addLocRect = self.buttonAddLocation.frame; // button 1
CGRect connectRect = self.buttonConnect.frame; // button 2
// This will be set below in one of the if-else branches
CGFloat buttonWidth = 0;
// determine the offset from the left/right based on device and orientation
int offsetLeft = 0;
int offsetRight = 0;
if ([self isIphone]) {
offsetLeft = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_LEFT_PORTRAIT_IPHONE : OFFSET_LEFT_LANDSCAPE_IPHONE;
offsetRight = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_RIGHT_PORTRAIT_IPHONE : OFFSET_RIGHT_LANDSCAPE_IPHONE;
} else {
offsetLeft = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_LEFT_PORTRAIT_IPAD : OFFSET_LEFT_LANDSCAPE_IPAD;
offsetRight = offsetLeft;
}
// change the size & location of the buttons to maximize the area for the location list
// no matter what orientation, the button frame will fill the bottom of the screen
saveRect.size.width = _windowWidth -offsetLeft - offsetRight;
// for Landscape, move the buttons to side-by-side at the bottom of the window
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
// size & move the buttons to fit side-by-side
buttonWidth = (saveRect.size.width)*.4;
// addLocRect.origin.x += offset;
addLocRect.origin.y = saveRect.size.height - addLocRect.size.height ;
connectRect.origin.x = saveRect.size.width - buttonWidth - offsetRight;
connectRect.origin.y = saveRect.size.height - connectRect.size.height;
} else { // Portrait
// move the buttons down to the bottom of the frame, stacked
// size the buttons to be fully across the screen
buttonWidth = saveRect.size.width-2*offsetLeft;
addLocRect.origin.y = 0 ; // at the top of the button view
addLocRect.origin.x = offsetLeft;
connectRect.origin.y = saveRect.size.height - connectRect.size.height;
connectRect.origin.x = offsetLeft;
}
connectRect.size.width = buttonWidth;
addLocRect.size.width = buttonWidth;
self.buttonAddLocation.frame = addLocRect;
self.buttonConnect.frame = connectRect;
Working on a game here and I've so far made a menu system for my game. I added three different buttons. I have everything sorted out except one thing.
So, I am using a normal if intersects method to see if the mouse and the button rectangle is colliding to play a sound effect. However, I don't know how to stop this sound and it's just looping itself all the time, until I remove the mouse from the button. I want to make it so that it only plays one time.
public void Update(MouseState mouse, GraphicsDevice graphics, SoundEffect soundEffect)
{
rectangle = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y);
Rectangle mouseRectangle = new Rectangle(mouse.X, mouse.Y, 1, 1);
if(mouseRectangle.Intersects(rectangle))
{
if (mouse.LeftButton == ButtonState.Pressed) isClicked = true;
size = new Vector2(graphics.Viewport.Width / 9, graphics.Viewport.Height / 13);
soundEffect.Play();
}
else
{
size = new Vector2(graphics.Viewport.Width / 10, graphics.Viewport.Height / 14);
isClicked = false;
}
Any help would be apreciated.
BTW: This is not neccesary, but I got another "problem" when I hover over the buttons, they get bigger which is intended. But it doesn't get bigger from the center. It's kind of hard to explain but it gets bigger in x and y position, not -x and -y. It has the same positon.
You're going to have to employ some status fields or events to do what you want. Something simple might be to track when the mouse enters and leaves the rectangle:
private bool _mouseIsIntersecting;
public void Update(...)
{
rectangle = new Rectangle(...);
Rectangle mouseRectangle = new Rectangle(...);
if(mouseRectangle.Intersects(rectangle))
{
// Handle click and size stuff
// Only play the sound if mouse was not previously intersecting
if (!_mouseIsIntersecting)
soundEffect.Play();
_mouseIsIntersecting = true;
}
else
{
_mouseIsIntersecting = false;
// Handle other stuff
}
}
I need to create something similar to a progress bar but which gradually moves to the right of the form over time instead of percentage of completion. Both the time and the distance need to be specified when calling the move method e.g. I want the object to move 200px to the right over 10 seconds.
I just wanted to get some suggestions as to what is the best way to go about it?
I was thinking of using a timer and moving the object 1px to the right after every tick and then limiting the time by setting a limit to the ticks. Also, the object needs to look like a straight vertical line. I was thinking of using an image of a line, since I am more familiar with this than drawing images, but would drawing a line, then redrawing it constantly (like dragging) be a better approach?
Something quick and dirty:
public Form1()
{
InitializeComponent();
const int maxWidth = 200;
const int maxTicks = 10;
var currentTick = 0;
// Create panel and add it to this form
var panel = new Panel { Location = new Point(1, 1), BackColor = Color.Blue, Width = 0, Height = 5 };
Controls.Add(panel);
// Create timer that handles updates
var t = new Timer { Interval = 1000 };
t.Tick += delegate
{
panel.Width = maxWidth / maxTicks * currentTick;
if (currentTick++ != maxTicks)
return;
panel.BackColor = Color.Green;
t.Dispose();
};
t.Start();
}