I'm trying to spruce up my Inspector but I'm having a lot of trouble trying to draw text at a specified position in the inspector. I have drawn a colored rectangle on the sample inspector below and want to draw text (like a label) on top of it.
How can I draw text/label at the "X" position shown above? I'm not really sure where to start. Any help would be greatly appreciated.
Implementing the answer:
public override void OnGUI(Rect position)
{
GUIStyle myStyle = new GUIStyle();
myStyle.fontSize = 16;
myStyle.alignment = TextAnchor.UpperLeft;
myStyle.padding.top = 5;
myStyle.padding.left = -3;
myStyle.fontStyle = FontStyle.Bold;
Color32 color = colorSpacer.drawColor; // Custom Property Attribute
EditorGUI.DrawRect(new Rect(position.x-11, position.y, position.width+11, position.height-2), color);
Rect r = GUILayoutUtility.GetLastRect();
EditorGUI.LabelField(r, "Section Header", myStyle);
}
If you are drawing your Custom Editor with EditorGUI, you can use the methods LabelField, PrefixLabel, SelectableLabel or HandlePrefixLabel, depending on your specific desired behavior.
If you are drawing with EditorGUILayout, there are equivalents of those methods.
Also, the HeaderAtribute decorator does that without need for a custom Editor.
Related
Is it possible to create a bar like this one in Unity?
The default components seem to work primitive only. I can have a rectangle as a bar or a radial bar.
This spiral bar would need to have access to a path because the color has to know how to move along the sprite.
I would use a custom shader with a sprite containing the "fill information" as the alpha channel.
On the image below, you will see your original sprite, and an other one with a gradient alpha (sorry, I'm not an expert with photoshop).
You can download the Unity shaders on their website, and pick the UI-Default.shader inside DefaultResourcesExtra/UI and tweak it a little bit so as to fill the sprite according to the alpha value of the sprite.
Something like this (not tested)
Shader "UI/FillAlpha"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_FillAmount ("Fill amount", Float) = 1
// ...
}
SubShader
{
// ...
sampler2D _MainTex;
fixed _FillAmount;
fixed4 frag(v2f IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
color.a = color.a > _FillAmount ? 1 : 0 ;
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
// ...
return color;
}
ENDCG
}
}
}
Then, you will be able to change the FillAmount parameter using myMaterial.SetFloat
You can use Line Renderer component to create your bar.
See documentation and examples here:
https://docs.unity3d.com/Manual/class-LineRenderer.html
https://docs.unity3d.com/352/Documentation/Components/class-LineRenderer.html
Note that Line Renderer works in a 3D space.
Sorry, I'll try to explain better.
I want to make a sliding menu where you can select a character. I want the character that is at the center increases in size to know that this is the current character. The effect can be seen in the game of Crossy Road when you want to select a character.
Sorry but I can't upload a imagen because i am new in the forum
I think I might be able to help you without needing too much borrowed code. There are two possibilities here:
You have a perspective camera so the "selected" item can just be closer to the camera.
You have an orthographic camera so you will have to scale things.
For perspective:
List<GameObject> characters; //contains all character.
int selectedIndex = 0; //index to the selected character.
float spacing = 10; //space between chars
void Update()
{
if(Input.GetKeyDown("RightArrow"))
{
selectIndex++;
ApplyChanges();
}
if(Input.GetKeyDown("LeftArrow"))
{
selectIndex--;
ApplyChanges();
}
}
void ApllyChanges()
{
// Make sure the selected index is within range and then space the characters.
selectedIndex = selectedIndex % character.Count();
SpaceCharacters();
}
void SpaceCharacters()
{
for(int i = 0; i < characters.Count(); ++i)
{
// characters on the left will have a negative spacing and so will be placed to the left and vice versa for characters on the right.
int offset = i - selectedIndex;
characters[i].transform.position = new Vector3(offset * spacing, 0, 0);
}
// Move the selected character closer.
characters[selectedIndex].transform.position = new Vector3(0,0,spacing);
}
For orthographic camera you will need to set the select characters transform.scale to a larger vector.
This won't animate anything or look cool. This code will just snap your characters into position.
The solution I adopted was to attach objects to the transparent buttons in a scrool rect, so as to manage 3d objects with the convenient of scrool rect interface.
Here you can find the official documentation for use scrool rect: http://docs.unity3d.com/Manual/script-ScrollRect.html
Maybe my assets can serve you ;)
https://www.assetstore.unity3d.com/en/#!/content/60233
I've an app which like the image shown below (sorry I used an iPhone like mock-ups)
The app has an image as background (displayed using Canvas which takes the whole visual screen size), then another shape (the red rectangle in this case) will shown above the background which can be dragged and pinch zoomed.
Now the question is:
How can I get the coordinates (origins from top-left corner of the screen, i.e. top-left of the canvas) of the top-left corner of the rectangle?
UPDATE
According to #Will's suggestion, I currently move the rectangle in this case via DragDelta using TranslateTransform inside it, like:
rectTransform.X += e.HorizonalChange;
rectTransform.Y += e.VerticalChange;
The rectangle is defined within code, not in XAML:
rect.Stroke = new SolidColorBrush(Colors.Green);
rect.StrokeThickness = 10;
rect.Fill = new SolidColorBrush(Colors.Transparent);
rect.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
rect.VerticalAlignment = System.Windows.VerticalAlignment.Center;
rect.Width = 200;
rect.Height = 200;
canvas.Children.Add(rect);
and the canvas is defined within XAML.
What I've tried:
Initially I was trying to get the start point when the Drag event begins, but by using the DragStarted(object sender, DragStartedGestureEventArgs e), I am only able to output the coords of the point which was touched, but not the point of top-left corner of this rectangle.
And it's similar to the DragCompleted event which will return me the point the gesture ends.
So is there any chance I can get the origin coords of the red rectangle?
I spent nearly an afternoon on Google as well as MSDN and then finally come to find this on SO:
How to get the position of an element in a StackPanel?
which enlightened me using the similar method. In that case, they managed to get the absolute coordinates of an UI Element. Similarily, in my case, I intend to know the absolute origin(coordinates) of the red rectangle to the background canvas.
I use:
GeneralTransform gt = canvas.TransformToVisual(rect);
Point currentPos = gt.Transform(new Point(0, 0));
Then the currentPos is the current position of rectangle (its an absolute position, relative to the canvas).
And Here's the reference of TransformToVisual in MSDN
There's only one thing to pay attention to: the value of X and Y are negative.
Not 100% sure of the syntax here, but in WPF (which should be analogous) I'd handle it by
private double _startX, startY, _endX, _endY;
private void DragStarted(object sender, DragStartedGestureEventArgs e)
{
var rect = sender as UIElement; // I'm assuming the sender is your Rectangle
this._startX = Canvas.GetLeft(rect);
this._startY = Canvas.GetTop(rect);
}
private void DragCompleted(object sender, DragCompletedGestureOrWhateverLolEventArgs e)
{
var rect = sender as UIElement; // I'm assuming the sender is your Rectangle
this._endX = Canvas.GetLeft(rect);
this._endY = Canvas.GetTop(rect);
}
What you say? Not type safe? Yeah, well, okay. How about give your rectangle an x:Name and then use that in these methods?
<Rectangle x:Name="rect" SkipOtherPropertiesLol="true" />
and
this._startX = Canvas.GetLeft(rect); //etc
Attached properties are a little confusing at first, but they are very powerful and easy to use once you understand their fairy magic.
This is not a duplicate of How to set SWT button foreground color?. It's more like a follow up. I wrote follow-up questions as comments, but did not get any responses, so I thought I'd try to put it up as a question, and hopefully some expert will see it.
As is pointed in the referenced question, windows native button widgets do not support setting the foreground color (in fact, after more further research (more like experiments), it's been revealed that setForeground() works under the Classic Theme, but not others).
The answer/suggestion given in the referenced question is a good one (a.k.a providing a paint listener and drawing over the text with the correct color). I gave it a whirl but ran into a world of problems trying to decide the coordinate at which to draw the text:
It appears that - in addition to SWT attributes like alignment etc. - Windows has some rather hard-to-figure-out rule of deciding the location of the text. What makes it worse is that the location appears to be dependent on the windows theme in effect. Since I need to draw the text exactly over the natively-drawn windows text in order to override the color, this is a huge problem.
Please, can someone provide some much-needed help here? It'd be greatly appreciated!
Thank you!
On the same PaintListener you use to paint the coloured background, you have to calculate the position and draw the text. Here's how we do it here:
public void paintControl( PaintEvent event ) {
// Is the button enabled?
if ( !isEnabled() ) {
return;
}
// Get button bounds.
Button button = (Button)event.widget;
int buttonWidth = button.getSize().x;
int buttonHeight = button.getSize().y;
// Get text bounds.
int textWidth = event.gc.textExtent( getText() ).x;
int textHeight = event.gc.textExtent( getText() ).y;
// Calculate text coordinates.
int textX = ( ( buttonWidth - textWidth ) / 2 );
int textY = ( ( buttonHeight - textHeight ) / 2 );
/*
* If the mouse is clicked and is over the button, i.e. the button is 'down', the text must be
* moved a bit down and left.
* To control this, we add a MouseListener and a MouseMoveListener on our button.
* On the MouseListener, we change the mouseDown flag on the mouseDown and mouseUp methods.
* On the MouseMoveListener, we change the mouseOver flag on the mouseMove method.
*/
if ( mouseDown && mouseOver ) {
textX++;
textY++;
}
// Draw the new text.
event.gc.drawText( getText(), textX, textY );
// If button has focus, draw the dotted border on it.
if ( isFocusControl() ) {
int[] dashes = { 1, 1 };
evento.gc.setLineDash( dashes );
evento.gc.drawRectangle( 3, 3, buttonWidth - 8, buttonHeight - 8 );
}
}
In the end, I decided to implement it as a custom Composite with a checkbox/radio button and a label. Not ideal, but I'll have to make do.
I am using Eclipse & JDE 4.5.0 plug-in. How to align fields vertically. Can we align fields like LEFT_BOTTOM,RIGHT_BOTTOM, LEFT_VCENTER, RIGHT_VCENTER, CENTER(vertically & horizontally), BOTTOM_CENTER, etc...?
BlackBerry UI field managers are notoriously annoying when dealing with field alignment. Managers seem to ignore all style flags (like HCENTER, VCENTER, etc) so the only way you'll be able to do this is to override the sublayout method of your manager and do it yourself.
Here's a little snippet to show you what I mean. This particular code actually does horizontal centering, not vertical centering, but once you get the idea you can implement any styles you need.
VerticalFieldManager mainmanager = new VerticalFieldManager(Field.USE_ALL_WIDTH | Field.USE_ALL_HEIGHT)
{
protected void sublayout( int width, int height ) {
super.sublayout( width, height );
width = getWidth();
height = getHeight();
for (int i = 0;i < this.getFieldCount() - 1; i++)
{
Field field = this.getField(i);
//this positions the item in the middle of the manager
int x = (int)((width - field.getWidth()) * 0.50);
setPositionChild(field, x, field.getTop());
}
}
Please note that the USE_ALL_WIDTH and USE_ALL_HEIGHT style flags are important. If you want to do things like vertical centering, bottom-right aligning, etc. you will need to write the positioning code yourself. For bottom-right alignment for example you could set the x position to the width of the manager minus the width of the field, and the y position to the height of the manager minus the height of the field.
If you want to be able to use one custom manager class to handle multiple different styles (like bottom right, bottom left) you can add some logic in sublayout to check the field's style flag and then position the field appropriately.
Hopefully this all makes sense and helps you. :)
HorizontalFieldManager only accepts Vertical Alignment Styles and VerticalFieldManager only accept Horizontal Alignment. That's it.
Annoying ++