Cloning a GUISkin? Or: Some GUILayout.TextField with alignment right

I have my own skin and I think it will be worked over by a real graphical artist one day.

so: I have some TextFields with numbers in them and want them aligned to the right. But I also have some TextFields aligned to the left.

I first thought: Make 2 skins with the inspector and just change the Alignment. But I cannot do that if the skin will be overhauled.

So I tried to clone a skin on Start() and just change the align:

InputAlignRightStyle=mainmenuSkin;
InputAlignRightStyle.textField.alignment=TextAnchor.MiddleRight;

But both var are pointing to the same reference so both skins will be modified. Then I tried using Instantiate() but I think it only works for Classes/Objects but not for Instances.

This:

InputAlignRightStyle=Instantiate(mainmenuSkin);

... throws a cryprical error:

metaFlags & kStrongPPtrMask
UnityEngine.Object:Internal_CloneSingle(Object)
UnityEngine.Object:Internal_CloneSingle(Object)
UnityEngine.Object:Instantiate(Object)
GuiScript:Start() (at Assets\GUI\GuiScript.js:34)

[..\..\Runtime\Serialize\TransferUtility.cpp line 352] 
(Filename: Assets/GUI/GuiScript.js Line: 34)

Any ideas?

Several workarounds come to mind.

1 . Non-programmatic: GUISkins can have any number of custom styles, in addition to the standard ones (Button, Label, etc.) The skin contains an array of them, so in the inspector you can change the array count, and use them for whatever you want.

You'd have to tell your artist to maintain the custom style(s) as well. To help keep things maintainable you might consider having a sample scene that demos all the styles that you're using in the app, that way the artist won't neglect any, or work on ones you aren't using.

2 . Programmatic: if most controls are left aligned you could simply save off the value of the alignment setting you want to override, change it to right-aligned, the restore it once you've drawn your right-aligned controls.

3 . Programmatic: it wouldn't take you long to write your own method to copy all the values from one GUIStyle to another. Downside is if Unity Tech adds or removes guistyle elements in future updates you will have to update your method as well. That risk/effort seems small to me.

You could combine 3 & 1: at program/scene start up, copy your text style to a custom style of the skin, changing the alignment. Then all objects referencing that skin would have access to the right-aligned style, and the artist wouldn't have to maintain it.

Hope these help.

You can do something like this (note: you'd want to store the variable outside of start, i've just layed it out like this for legibility of type):

GUIStyle textFieldStyle = new GUIStyle("textfield");
textFIeldStyle.anchor = TextAnchor.MiddleRight;

Note: if you clone the GUIStyle this way, you need to pass it to the TextField as the last parameter

Actually, Instantiate works for a GUISkin… you just need to remember to a) only instantiate it once (not every run through your OnGUI() method!), and b) to Destroy it when you’re done, or just let the scene transition destroy it naturally.

This appears to make an entire copy of a GUISkin (all its GUIStyles) and then you can modify those, and it won’t modify the original asset.

With that in mind, doing it this way is a bit “heavyweight,” and generates quite a few new objects. I found this out the hard way by inadvertently Instantiate()-ing a copy each frame. :slight_smile:

I’ve had a devil of a time with this too… (I was referencing a Style from a GUISkin, and the font-size changes I was making in the Style that were supposed to be temporary, were being imprinted in the GUISkin’s permanent settings.)

I’ve not yet found a way to clone a whole GUISkin in a way where changes to the copy would not effect the original…

…But I’ve found this solution where I can create a clone of a specific Style within the referenced GUISkin (eg: box, textField, customName, etc.) where changes to that style do not impact the originally referenced GUISkin

__

I’ve run this solution several times and it looks to me like it tests-out fine: the original GUISkin values never change as my other scripts muck-about with all the different font-re-sizing I need:

(Declarations)

var skinWithStyleIWant: GUISkin;
private var clonedStyle: GUIStyle;

(In Start)

clonedStyle = new GUIStyle(skinWithStyleIWant.GetStyle("outlined"));

.

…Where the style I want to clone is a custom style named, “outlined”

I think what you wanna do is clone a GUIStyle:

GUIStyle clone = new GUIStyle (orig);
clone.anchor = TextAnchor.MiddleRight;
GUILayout.TextField("hello", clone);