Saturday 31 July 2021

Android Java to Kotlin migration by example part 12: a few Kotlin features

Today I'm not going to use the format typical for this series, instead - I'll just show you two features of Kotlin I've just learned about. As there are no named arguments and default parameter values in Java, I cannot provide you the Java code counterpart this time :)

Kotlin functions have named arguments, actually exactly as in Python.

What that means (assuming you haven't read the previous post?). Well, let's consider the following code:

package com.mypackage

fun divide(nominator: Float, denominator: Float): Float{
return nominator/denominator
}
fun main() {

val result = divide(10.0f,5.0f)
val result2 = divide(nominator = 10.0f, denominator = 5.0f)
val result3 = divide (denominator = 5.0f, nominator = 10.0f)

println(result)
println(result2)
println(result3)
}

It produces the following result:

2.0 2.0 2.0

The function divide has (quite obviously) two arguments: nominator and denominator. If you call the function without specifying their names, their order matters: in our case, the first argument is divided by second one.

But... You can also call our function with named parameters: as in Python, here also it means you can switch their order (the calls initializing result2 and result3.

And second thing: also exactly as in Python, the parameters in Kotlin can have default values.

So that the following code, for example:

fun power(base: Float, exponent: Float = 2.0f): Float{
return base.pow(exponent)
}
fun main() {

val a2cubed = power(10f,3f)
var a2squared = power(10f)

println(a2cubed)
println(a2squared)
}

... makes power function actually a square function, when called with just one argument.

The code above produces the following result:

1000.0
100.0

I think that's all for today. Both named parameters and default values are neat features - especially in functional language - and another advantage of Kotlin over Java - it's good to know they're available.

Wednesday 28 July 2021

Unity editor scripting (part 4): basic scene management

If you have lot of assets in your project, and multiple scenes in particular, it can be hard to navigate between them.

I've encountered two basic problems while working in Unity:
1) doing something (or checking something) in multiple scenes
2) running a particular scene which is required to run for your game (for instance, it loads all assets), while working on another one.

This is where editor scripts come to the rescue :)

In the following code I'll show how to create a tool for iterating over enabled scenes (and logging their root count object as an example), and another - for simply running some chosen scene.

Create a file ScenesHelper.cs and put it in Assets/Editor folder of your project.

The code is simple:

using UnityEditor;
using System.Linq;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

class ScenesHelper
{
    static EditorBuildSettingsScene[] GetEnabledScenes()
    {
        return  EditorBuildSettings.scenes
          .Where(s => s.enabled).ToArray();
    }

    static string[] GetEnabledSceneNames()
    {
        var scenes = GetEnabledScenes()
            .Select(s => s.path)
            .ToArray();

        return scenes;
    }
    
    [MenuItem("Tools/Iterate over scenes. %#p")]
    static void Iterate()
    {
        foreach (string s in GetEnabledSceneNames())
        {
            Scene scene = EditorSceneManager.OpenScene(s);
            Debug.Log("Root object count in scene" + 
                scene.name 
                + ": " + scene.rootCount);
        }
    }

    [MenuItem("Tools/Play particular scene. %#o")]
    static void PlayScene2()
    {
        EditorSceneManager.OpenScene(
            GetEnabledSceneNames()[2]);
        EditorApplication.isPlaying = true;
    }

}

The method GetEnabledScenes() returns all enabled scenes (by omitting the Where clause you can also include those not enabled), or to be precise - objects of class EditorBuildSettingsScene , which represents scenes "identifiers" in editor build settings. 
The method GetEnabledSceneNames() returns their paths/names (retrieved via Linq Select).

Then we have the method Iterate()  (available from the Tools menu or via Ctrl+Shift+P shortcut) which iterates over all the enabled scenes (using their names) and logs the root objects count for each of them, and  PlayScene2() (Tools menu or Ctrl+Shift+O) which makes the editor play the second scene in our list.

Please note opening a scene in  Iterate() uses Scene class object, returned by EditorSceneManager.OpenScene(s) - it's not the same as EditorBuildSettingsScene. The former represent Unity scenes with objects, which can be inspected or played, the latter is sort of id of a scene in editor build settings.

Sunday 25 July 2021

Tray icon management in Windows Forms C# app

Today something different. The problem I’ll write about is: how to make a Windows Forms (C#) app minimize to tray when cliked on „X” and prevent it from displaying in the taskbar.

In other words – how to make a „typical tray app”.

To be honest – I was quite sure there would be some component (control) for it.

And there is (NotifyIcon) but… It’s not enough just to drag it to our app designer form in Visual Studio to make it work as we would like to.

Let’s begin with opening Visual Studio and creating a new Windows Forms App:

File -> New -> Project -> Windows Forms Apps -> Ok

First, wee drag NotifyIcon component from Toolbox to our form (it will appear below it, as it’s not visible in the form area, but outside it)



And here is the first strange behaviour: if we run (F5 or Ctrl+F5, but i’d suggest F5 as it allows it to kill the app if something goes wrong, and it can in this case) our app, the NotifyIcon component doesn’t seem to work. The tray icon doesn’t show up, and neither minimization nor clicking the „X” button causes our app to minimize to tray.

That’s because our tray icon is not set and we haven't implemented minimization by clicking "X". First the icon: in order to set it, we need the tray icon itself :)

We can just use Paint to create it – set the canvas size to 16x16 (this is the standard tray icon size in Windows), draw something beautiful and save it as .jpg file. Now rename it to something.ico – simply change the extension! The ico files are simply graphics files with a particular extension.

Now you can copy it to project – you can just drag it to project name in Solution Explorer view in VS.



It should show up below (myicon.ico) in the image above.

Now if you hit F5, the icon should show in the tray :)

The problem is it doesn’t do anything. The app still minimizes to the taskbar.

So let’s edit the code. Double click on the form project appearing in VS. The form code should appear, and it should be similar to this:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object senderEventArgs e)
        {

        }
    }
}

 

First of all, let’s make our icon actually do something: it should show form if clicked twice, and hide it if clicked twice again. In order to do it, select our NotifyIcon component in the designer (Form1.cs [ Design] tab):


Now select the lightning icon in Properties windows (F4 if the window is not visible), click the empty area on the right of „MouseDoubleClick” and then double click on it again :)



 An empty method should appear in the editor:


private void notifyIcon1_MouseDoubleClick(object senderMouseEventArgs e)
{

}

Let's implement it:


private void notifyIcon1_MouseDoubleClick(object senderMouseEventArgs e)
{
    if (this.Visible == true)
    {
        this.Hide();
    }
    else
    {
        this.Show();
    }
}

Now when you run the app and double click on the tray icon, the window should disappear. Double click on the icon again, and the window should appear. Now close the window – let’s get back to the code: we’ll add a context (right click) menu to the tray icon.

The remaining problems are as follows: the application exits, when we click „X” in the top bar. This is correct behaviour for most apps, but those enabled on tray should keep working even if „X” is clicked (the typical way of closing them is to right click on the tray icon and choosing „Close” or something similar from the context menu). The second problem is: the application still appears on the „normal” taskbar, and we want it to be minimized only to tray.

To fix the first issue, modify the Form1 constructor in this way:  


public Form1()
{
    InitializeComponent();
    this.FormClosing += this.Form1_FormClosing;
}

 … and add the callback for FormClosing event below:


private void Form1_FormClosing(object senderFormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.UserClosing)
    {
        this.Hide();
        e.Cancel = true;
    }
}

If you want to run the app now, do it using F5 (not Ctrl+F5) – you’ll need to terminate it using „Stop Debugging” (red square button or Shift+F5 in Visual Studio). If you forget about it, you’ll have to close it via the task manager :)

Now let’s add a possibility of closing the app via the context menu for the tray icon. In order to do that, switch to the Form1.cs [Design] view and drag ContextMenuStrip component to your designer view (window).



Now click on the "Type Here” area, type "Exit” and double click on it. It should take you to the editor, with generated code stub:


private void exitToolStripMenuItem_Click(object senderEventArgs e)
{

}

We want to close app when choosing ‘Exit’ option, so implement like this:


private void exitToolStripMenuItem_Click(object senderEventArgs e)
{
    Application.Exit();
}

Of course, you can add more items to the menu (and add whatever code you want to it).

The last thing to do is to attach this menu to our tray icon. In order to do that, choose notifyIcon1 from the area below the designer:



 ...and choose our ContextMenuStrip in the Properties window on the right:



When you run the app now and right-click on the tray icon, "Exit” option should appear (and should work).

To last thing to do is to prevent the app from showing on the "normal” taskbar. To do this, add one last line to Form1 constructor:


public Form1()
{
    InitializeComponent();
    this.FormClosing += this.Form1_FormClosing;
    ShowInTaskbar = false;
}

That's all for today - I think I was able to show you a simple stub of Windows app using tray in C#. If you have any questions about this - ask them in comments :)

Saturday 24 July 2021

Python crash course part 8: file input and output

In today's post I'll provide some short samples of working with files in Python.

Let's begin with text files and let's create a file first.

# !/usr/bin/python3

def main():
    # create a file
    my_file = open('newfile.txt''w')
    # write some data to it:
    my_file.write("Anakin Skywalker")
    my_file.close()

    # contents of the file: 
    # Anakin Skywalker

if __name__ == "__main__":
    main()

The result of running this code is creating a file newfile.txt with content: Anakin Skywalker

'w' means that the we will write to the file, and if that file exits, it will be overwritten. Remember to call .close() on the file object after opening and doing some operation on it.

Let's extend our program, by calling the similar code again:

# !/usr/bin/python3

def main():
    # create a file
    my_file = open('newfile.txt''w')
    # write some data to it:
    my_file.write("Anakin Skywalker")
    my_file.close()

    # contents of the file: 
    # Anakin Skywalker

    # opening it again
    my_file = open('newfile.txt''w')
    my_file.write("Darth Vader")
    my_file.close()

    # contents of the file: 
    # Dath Vader

if __name__ == "__main__":
    main()

As the 'w' mode makes the write call overwrite the file contents, it will be just Darth Vader  after the call. What if we want to actually add something to the file, not deleting it contents?

That's what 'a' (append) mode is for:

# !/usr/bin/python3

def main():
    # create a file
    my_file = open('newfile.txt''w')
    # write some data to it:
    my_file.write("Anakin Skywalker")
    my_file.close()

    # contents of the file: 
    # Anakin Skywalker

    # opening it again
    my_file = open('newfile.txt''w')
    my_file.write("Darth Vader")
    my_file.close()

    # contents of the file: 
    # Dath Vader
    my_file = open('newFile.txt','a')
    my_file.write("\nLuke Skywalker")
    my_file.close()
    # contents:
    # Darth Vader
    # Luke Skywalker


if __name__ == "__main__":
    main()

Because 'a' mode is used instead of 'w', \nLuke Skywalker is added (appended) to the existing file. The \n before the text itself in the third write call is a new line sign between the first and second line. The contents of the file become:

Darth Vader
Luke Skywalker

We know how to write to file, but how to read from it? This is what open() with 'r' (read) parameter is for. We use it like this:

# !/usr/bin/python3

def main():
    # create a file
    my_file = open('newfile.txt''w')
    # write some data to it:
    my_file.write("Anakin Skywalker")
    my_file.close()

    # contents of the file: 
    # Anakin Skywalker

    # opening it again
    my_file = open('newfile.txt''w')
    my_file.write("Darth Vader")
    my_file.close()

    # contents of the file: 
    # Dath Vader
    my_file = open('newFile.txt','a')
    my_file.write("\nLuke Skywalker")
    my_file.close()
    # contents:
    # Darth Vader
    # Luke Skywalker
    
    to_read = open('newFile.txt','r')
    file_contents = to_read.readlines()
    for val in file_contents:
        print(val)

    #result:
    #Darth Vader
    #
    #Luke Skywalker   

if __name__ == "__main__":
    main()

The code above creates the file, adds 2 lines (Darth Vader and Luke Skywalker) to it, and the reads lines from the file, puts them in file_contents variable (list) and prints them to console.

The execution result is therefore:

Darth Vader

Luke Skywalker

As you can see, there is something strange with this result: there is an empty line between Darth and Luke, which is not in the file. That's because print(val) adds a new line character after the text it prints, and there is already one new line between Darth Vader and Luke Skywalker in the file.

In order to fix it, we can use an overloaded version of the print() function: print(val,end=''), which specifies that in the end of the text it should use an empty character instead of new line:

# !/usr/bin/python3

def main():
    # create a file
    my_file = open('newfile.txt''w')
    # write some data to it:
    my_file.write("Anakin Skywalker")
    my_file.close()

    # contents of the file: 
    # Anakin Skywalker

    # opening it again
    my_file = open('newfile.txt''w')
    my_file.write("Darth Vader")
    my_file.close()

    # contents of the file: 
    # Dath Vader
    my_file = open('newFile.txt','a')
    my_file.write("\nLuke Skywalker")
    my_file.close()
    # contents:
    # Darth Vader
    # Luke Skywalker

    to_read = open('newFile.txt','r')
    file_contents = to_read.readlines()
    for val in file_contents:
        print(val,end='')

if __name__ == "__main__":
    main()

The execution of the code above finally results in:

Darth Vader
Luke Skywalker

... which are contents of the file created above :).

We've covered text files - what about binary files? Here we're going to focus on reading from such file (let's be honest - writing to binary file is not very commond situation).

And reading from binary files is easy: we have to set 'rb' (read binary) instead of just 'r' (read) as our file open mode, and then we can read, for instance, a few bytes from the file. Those bytes become bytes array. So if we have, for instance, wav file (which should begin with letters RIFF in ASCII form), the reading of a first fragment of such file would look like this:

# !/usr/bin/python3

def main():

    binary_file = open('sound.wav','rb')
    bytes = binary_file.read(4#bytes
    print(bytes[0])
    print(bytes[1])
    print(bytes[2])
    print(bytes[3])
    
    print(str(bytes))

if __name__ == "__main__":
    main()

Which results in:

82
73
70
70
b'RIFF'

(which means it looks like some wav file indeed :) )

Thursday 22 July 2021

Python crash course part 7: more on defining functions

 In the part 2 we've shown most basic ways of definining functions in Python.

Let's elaborate on that a bit more, using some examples.

First, a simple function just doing something, for instance printing text to screen (something tradinionally called a procedure rather than a function), is defined like this:

def just_do_it():
    print("Just do it")

... and called like this:

    just_do_it()

So execution of the program below:

# !/usr/bin/python3

def just_do_it():
    print("Just do it")

def main():

    just_do_it()

...results in the following output:

Just do it

What if we want to return value from function, so we can use it in the moment it's called? Well, let's simply use return keyword:

def please_return_something():
    return 3.14

The type doesn't have to be defined.

As an example we'll assign the value returned by the function above to pi variable, and then print it to the screen.

def main():

    pi = please_return_something()
    print(pi)

Result:

3.14

What if we want our function to take some parameters?

This is when the things became interesting, as Python allows us to defined both named and unnamed (positional) paramaters. By default, both. So we can define our function as:

def divide(nominatordenominator):
    return nominator/denominator

...and call it in two ways:

    print(divide(6,2))

Or:

    print(divide(nominator=6,denominator=2))

...both resulting in:

3.0

Please note that if we call our function with named parameters, their order doesn't matter. So call:

    print(divide(denominator=2,nominator=6))

...also results in:

3.0

The last thing for today will be default parameter value, which is defined using the = sign.

An example looks like this...

def power(ab = 2):
    return a**b

( ** is power operator, a**b means a to the power of b).

The above function has two parameters, but the second one (exponent) has default value. This means that if we skip the second param, our function becomes simply square function.

So the "full-param" call looks like this:

    print(power(2,3))

...and results in:

8

And the call using default parameter value can look like this:

print(power(3))

..resulting in:

9

There are more details about defining and calling functions in Python, which we can elaborate further on in future, but I think for now we've covered the most important features.


Tuesday 20 July 2021

Python crash course part 6: basic exceptions.

Another basic language feature I'll cover in this tutorial is exception handling (which I wrote about in Kotlin a few days ago.

Traditionally, I'll show some examples. Let's begin with simple code, asking user for two numbers and dividing them. Of course, such program may encounter probably the most basic exception: division by 0. But also another one: if we put something not being a number, it cannot be converted to float and some other exception would be expected.

First, the code without any exeption handling would look like this:

# !/usr/bin/python3

def divide(ab):
    return a/b

def main():
    a = float(input('a = '))
    b = float(input('b = '))
    c = divide(a,b)
    print(c)

We create a function divide(ab) , returning division result. Then we get two numbers from user, a and b using input('... ') function and converting them to float using float() function (as input('a = ') returns simply a string).

If given two numbers which we can divide by eachother, the result is not surprising:

a = 10
b = 3
3.3333333333333335

But if we put 0 as b...

a = 10
b = 0
Traceback (most recent call last):
  File "d:\Projekty\Python\controlflow.py", line 13, in <module>
    main()
  File "d:\Projekty\Python\controlflow.py", line 9, in main     
    c = divide(a,b)
  File "d:\Projekty\Python\controlflow.py", line 4, in divide   
    return a/b
ZeroDivisionError: float division by zero

... we get a cute stacktrace. Well, division by 0 is not possible, and therefore results in an exception. Quite obvious :)

Before we try to deal with this proble, let's put another strange data as input to program: try to divide 10 by horse. Well, this also shouldn't be possible, right?

a = 10
b = horse
Traceback (most recent call last):
  File "d:\Projekty\Python\controlflow.py", line 17, in <module>
    main()
  File "d:\Projekty\Python\controlflow.py", line 9, in main
    b = float(input('b = '))
ValueError: could not convert string to float: 'horse'

... as expected. Of course, here another exception is caught (and in other place: not when trying to divide, but when trying to get float from quite horse-like input...)

What can we do with exception? We can catch it. First, a general exception:

# !/usr/bin/python3


def divide(ab):
    return a/b

def main():
    
    try:
        a = float(input('a = '))
        b = float(input('b = '))
        c = divide(a,b)
        print(c)
    except:
        print("Some exception caught!")

if __name__ == "__main__":
    main()

...which handles both division by 0:

a = 10
b = 0
Some exception caught!

... and division by horse :) 

a = 10
b = horse
Some exception caught!

The exception handling in Python is done using try except instruction. In the case above, no specific exception has been specified to be caught, so we get the same result in case of any exception (also known as Pokemon exception handling... Catch them all ;) ).

So what if we wanted to catch some specific exception? 

# !/usr/bin/python3


def divide(ab):
    return a/b

def main():
    
    try:
        a = float(input('a = '))
        b = float(input('b = '))
        c = divide(a,b)
        print(c)
    except ZeroDivisionError:
        print("Division by 0? Blasphemy!")

if __name__ == "__main__":
    main()

Result:

a = 10
b = 0
Division by 0? Blasphemy!

What if we want to catch more specific exceptions?

We can specify more except blocks:

# !/usr/bin/python3


def divide(ab):
    return a/b

def main():
    
    try:
        a = float(input('a = '))
        b = float(input('b = '))
        c = divide(a,b)
        print(c)
    except ZeroDivisionError:
        print("Division by 0? Blasphemy!")
    except ValueError:
        print("Some strange value...")

if __name__ == "__main__":
    main()

Division by 0 is then detected separately from division by horse:

a = 10
b = 0
Division by 0? Blasphemy!

and

a = 10
b = horse
Some strange value...

That's all for now - the custom exceptions and throwing them "by hand" will be one of our next topics in the nearest future :)



Python crash course part 10: inheritance and polymorphism

In the last part we've shown how to create and use a class in Python. Today we're going to talk about inheritance: wchich means cre...