Unity How do I capture GameView in my EditorWindow - unity3d

I'm making a simple leveleditor window for my game and I want to capture GameView image to that leveleditor window. I'm using ScreenCapture.CaptureScreenshotAsTexture() but it gives the image of leveleditor window, I also try Texture2d.ReadPixels but it gives the same result.

You could have a look at my answer here. I wrote a script that can capture any window that is currently focused.
You could easily adopt it to allways make the GameView the captured window. For example using reflection like this (source)
public static EditorWindow GetMainGameView()
{
var assembly = typeof(EditorWindow).Assembly;
var type = assembly.GetType("UnityEditor.GameView");
var gameview = EditorWindow.GetWindow(type);
return gameview;
}
and replacing
var activeWindow = EditorWindow.focusedWindow;
with
var activeWindow = EditorWindow.GetMainGameView();
Note that this will open a new GameView window if none was there yet.

Related

Sprites added to Unity SpriteLibraryAsset programmatically doesn't appear in asset

I am creating a Unity Editor script which takes a texture, slices it (this part works) and adds these sprites to a selected SpriteLibraryAsset:
foreach(var currentGroup in selectedDefinitionFile.Groups)
{
for (int i = 1; i <= currentGroup.Item2; i++) {
var rects = dataProvider.GetSpriteRects();
var targetName = String.Format("{0}-{1}", currentGroup.Item1, i);
var sprite = (Sprite)allSprites.Where(x => x.name == targetName).First();
spriteLibraryToPopulate.AddCategoryLabel(sprite, currentGroup.Item1, i.ToString());
}
}
// None of these do anything
spriteLibraryToPopulate.SetDirty();
EditorUtility.SetDirty(spriteLibraryToPopulate);
AssetDatabase.SaveAssets();
AssetDatabase.SaveAssetIfDirty(new UnityEditor.GUID(AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(spriteLibraryToPopulate))));
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(spriteLibraryToPopulate));
AssetDatabase.Refresh();
UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
If I run this script multiple times and stop on a breakpoint, I can see in Visual Studio that the sprites are being added as expected to the in-memory object. However, when I examine the Sprite Library asset, both in the editor and in the asset file using Notepad++, none of them appear.
Reimporting via the menu in the editor does nothing as well.
Investigation with a debugger shows that internally, Unity uses the class SpriteLibrarySourceAsset when importing a .spriteLib asset and creates the SpriteLibraryAsset I have access to in my scripts. I haven't been able to find how to go the other way.
I finally was able to achieve what I intended using reflection to call some internal Unity APIs.
// Perform your modification to the sprite library before this
// The logic to transform the SpriteLibraryAsset to the internal representation works on the selected objects.
Selection.objects = new UnityEngine.Object[]
{
spriteLibraryToPopulate
};
var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(spriteLibraryToPopulate)) as SpriteLibrarySourceAssetImporter;
var saveMethod = typeof(SpriteLibrarySourceAssetImporter).GetMethod("ConvertToSourceAsset", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
saveMethod.Invoke(null, null);
var rootPath = Path.Join(AssetDatabase.GetAssetPath(spriteLibraryToPopulate), "..");
// The save logic creates a differently named instance of the asset, so we copy the data from our newly created one into the original
File.Copy(Path.Join(rootPath, string.Format("{0} 1.spriteLib", spriteLibraryToPopulate.name)),
Path.Join(rootPath, string.Format("{0}.spriteLib", spriteLibraryToPopulate.name)), true);
// Get rid of the extra asset and its associated meta file.
File.Delete(Path.Join(rootPath, string.Format("{0} 1.spriteLib", spriteLibraryToPopulate.name)));
File.Delete(Path.Join(rootPath, string.Format("{0} 1.spriteLib.meta", spriteLibraryToPopulate.name)));
At the end, the library should be selected in the Unity Editor. If you try and click away, it will be marked dirty and Unity will prompt you to save or revert; it appears to me that both have the same result.

How to remove deleted scenes from build settings

After adding scenes to build settings then deleting them, the deleted scenes are still showing up. Problem is its affecting scene count. They all show up as a valid scene even though it says deleted. Highlighting them all and selecting remove selections does nothing.
EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes;
Debug.Log(scenes.Length);
This log statement returns ALL scenes even the deleted ones.
You could filter out all EditorBuildSettingsScene which have a File.Exists(scenePath) = false like
using System.IO;
using System.Linq;
using UnityEditor;
public static class EditorBuildSettingsTools
{
[MenuItem("CustomBuildTools/RemoveDeletedScenes")]
public static void CleanUpDeletedScenes()
{
var currentScenes = EditorBuildSettings.scenes;
var filteredScenes = currentScenes.Where(ebss => File.Exists(ebss.path)).ToArray();
EditorBuildSettings.scenes = filteredScenes;
}
}
Place this into a folder named Editor so it is excluded from a build e.g. like
Assets/Editor/EditorBuildSettingsTools.cs
The solution of derhug can not seems working. For example, when you delete a folder via script that contain scene and call the method CleanUpDeletedScenes the file scene exist in same frame because it is in cache. I advice of use the method AssetDatabase.LoadAssetAtPath to check if exist scene file:
public static void CleanUpDeletedScenes() {
currentScenes = EditorBuildSettings.scenes;
var filteredScenes = currentScenes.Where(ebss => AssetDatabase.LoadAssetAtPath(ebss.path, typeof(SceneAsset)) != null).ToArray();
}

Private integer not updating

Trying to write a script that's on several different objects where on mouseclick, 1 is added to a defined variable which then prints out. Currently when I click the objects, 1 is always printed.
#pragma strict
import UnityEngine.UI;
var theImage:UnityEngine.UI.Image;
var theSprite:Sprite; //The image you want to drag in the inspector
private var clickCount = 0;
function OnMouseDown () {
theImage.sprite = theSprite;
clickCount++;
Debug.Log(clickCount);
}
Here's my script. It also changes a GUI sprite. Seems like an easy fix, not sure where I've gone wrong.

Scripting GUI buttons to trigger an event of changing materials

Apologies if there's a similar question, however, I have probably seen it and it has not fixed my problem.
I am trying to write a JS script for unity in order to achieve an event to be triggered once clicked.
I have searched online on UnityAnswers website and others, the closest I can get is based on these questions
http://answers.unity3d.com/questions/368303/changing-shaders-of-a-gameobject-via-script-1.html
and this one
http://answers.unity3d.com/questions/319875/change-objects-material-using-gui-buttons-via-scri.html
and also looked at this one
http://docs.unity3d.com/ScriptReference/Material-shader.html
So, my code is this so far
var button2_tex : Texture;
var button3_tex : Texture;
var button4_tex : Texture;
var seat_mat1 : Material;
var seat_mat2 : Material;
var veneer1 : Texture;
var veneer2 : Texture;
var rend : Renderer;
var _mouseDown = false;
function Start() {
seat_mat1 = Resources.Load( "seat_mat1" );
seat_mat2 = Resources.Load( "seat_mat2" );
}
function Update(){
if(Input.GetMouseButtonDown(0)){
_mouseDown = true;
}
}
function OnGUI() {
GUI.Box (Rect (10,10,100,200), "Menu");
if (_mouseDown){
if (GUI.Button (Rect (20,40,40,20), button1_tex)){
if(seat_mat1){
rend.material = seat_mat2;
Debug.Log("This button was clicked!");
}
else{
rend.material = seat_mat1;
}
}
}
Please note some variables I haven't used yet, as am still testing bunch of other codes to get it working..
the code snippet I am trying to fix starts with "function OnGUI()" but I maybe wrong and could use some fresh insight.
this is a screenshot of the resulting script. The button on the left side is supposedly to change the colour of the material from seat_mat1 to seat_mat2 by the event of mouse clicking on the button.
I have attached the previous script to the 3D object in unity and had made a folder names "Resources" for the materials to be visible and referenced through the script.
My problem is that upon clicking the GUI button, nothing happens, and it maybe something very simple and I am just missing it .. apologies for being inexperienced in JS much or unity.
Thanks in advance.
EDIT:
So after playing a bit more with the code. I added a Debug.Log() after this line
GetComponent.<Renderer>().material = seat_mat2;
Debug.Log("This button was clicked!");
and seems to be this error that I am getting every time the button is pressed
"MissingComponentException: There is no 'Renderer' attached to the "scene_export3" game object, but a script is trying to access it.
You probably need to add a Renderer to the game object "scene_export3". Or your script needs to check if the component is attached before using it.
materialChanger.OnGUI () (at Assets/materialChanger.js:44)"
So with simple understanding, it seems that the renderer is not attached somehow?
Your code is working fine But still i think once you have loaded The materials in start function you do not need to load them every time. And one thing more is to make sure you have applied the script to the gameobject you want to change the material of. If you just want to change the color not want to change complete material use color property of material and your OnGUI function should look like this.
function OnGUI() {
GUI.Box (Rect (10,10,100,200), "Menu");
if (_mouseDown){
if (GUI.Button (Rect (20,40,40,20), button1_tex)){
if(GetComponent.<Renderer>().material == seat_mat1)
GetComponent.<Renderer>().material.color = seat_mat2.color;
else
GetComponent.<Renderer>().material.color = seat_mat1.color;
}
}
}
But if you do not use color poperty it will work fine just make sure you have applied script to game boject you want to change material i your case may be to your seat1.
Thanks Nain for your guidance, with your help I was able to come up with a partial solution, where I know I can fix from there.
The solution is as follows.
The code:
function OnGUI() {
GUI.Box (Rect (10,10,100,200), "Menu");
if (_mouseDown){
if (GUI.Button (Rect (20,40,40,20), button1_tex)){
var rendArray : Renderer[];
rendArray = GetComponentsInChildren.<Renderer>(true);
for(var rend : Renderer in rendArray){
if(rend.sharedMaterial == seat_mat1){
rend.sharedMaterial = seat_mat2;
Debug.Log("This button was clicked!");
}
else{
rend.sharedMaterial = seat_mat1;
}
}
}
}
}
After saving the script in MonoDevelop, open Unity where you create an empty game object and add all the objects with specific material e.g. seat_mat1 under it as children.
Then click on the empty object, rename it if you like, and add a "Mesh Renderer" component from "Add Component > Mesh > Mesh Renderer".
After that drag the script to the empty object and in the inspector you can find an option which you can choose a renderer called "rend". Choose the empty object as the Mesh Renderer.
Upon testing the outcome, I have managed to change materials of some objects together to seat_mat2, but unrelated materials changed themselves to seat_mat1 and once the button is clicked again, they alternate between seat_mat1 and seat_mat2
and even though it is not perfectly done, I am answering this question as anything else is fixable (I hope).
Thank you again Nain for your help :)

Unity 5 change button text created with UnityScript

In my 2D project I create a canvas and a button in code. I would like to set the text of the button in code, but after numerous attempts I can't seem to do it.
My UnityScript code:
#pragma strict
var loginButton : UnityEngine.UI.Button;
function Start () {
var canvas = new GameObject ("canvas", Canvas);
var instance : UnityEngine.UI.Button = Instantiate(loginButton);
instance.GetComponent(UnityEngine.UI.Text).text = "login"; //Error below
instance.transform.position = Vector2(0,0);
instance.transform.SetParent(canvas.transform);
}
This provides an error
"NullReferenceException: Object reference not set to an instance of an object
GameLogicLogin.Start () (at Assets/GameLogicLogin.js:11)"
--------------------------------Edit---------------------------------------
The generated hierarchy looks like this: http://puu.sh/iMYe6/4f4a8f545c.png
On the left at the bottom is the prefab I link to the script.
The following line doesn't cause an error and seems to change the text, but the change doesn't show up in game nor does the original text assigned to the "Text"in the prefab.
instance.GetComponentInChildren(UnityEngine.UI.Text).text = "login";
If you would of built your button in the unity editor you could easily change its text in script like this:
var button = GameObject.Find("buttonObjectName").GetComponent<Button>();
button.GetComponentInChildren<Text>().text = "What ever you like";
I imagine you can easily adjust this to fit your needs without being spoon fed.
You are instantiating a UnityEngine.UI.Button, that doesn't have a component for UnityEngine.UI.Text hence the error.
Is there any reason why you are instantiating that object?
If you are linking in the editor a game object to loginButton, and I think you are, you should do something like this:
var comps = loginButton.gameObject.GetComponentsInChildren(UnityEngine.UI.Text);
comps[0].text = "login";