Thursday, October 3, 2019

Generating "Always On Top" NSWindow in macOS across all detected displays

Also: Using UIKit & Cocoa Frameworks using Objective-C

In macOS or OS X, written in either Objective-C or Swift Langues, you may want an application to run both in full screen and at the top most level in the window layers, covering all apps behind it. This is known in some circles as the Z-Order or z dimension in a x-y-z Cartesian Plane. It's aptly named after Frenchman Rene Descartes, a highly revered & gifted Mathematician, and also Philosopher who made invaluable contributions to his respective fields. The x, y is the horizontal axis and vertical axis, while z-axis is the depth when you visualise the screen in three dimensions (3-D).

This snippet below I had written in Obj-C, and can be ported to Swift easily. The function is quite rudimentary in syntax and structuring. In a nutshell it enumerates all of the displays, and places a semi-transparent window, running full screen with a floating point opacity alpha value. If you want the background apps to still be visible then it's imperative that you set a low alpha float value (<= 0.5f).

Also, there are plenty of customisations possible to configure with classes NSScreen, NSWindow, and more. You can add a fullscreen subview from an NSImage or NSImageView and affix it to the primary screen, or all screens, whichever you fancy. There are also passed arguments specifying various colour values using class NSColor (can be specified in either hexadecimal #fffff or RGB float values eg: {1f,1f,1f}). You can also customise the behaviour of the full screen window, whether it can be resized or borderless, it's completely up to you! There are a plethora of possible configurations and styles defined in the class specifications or header.

This first function is a helper function that returns a UIImageView object based on input of image and frame, which are arguments passed into method. It sets the boundaries and affixes the NSImage as an NSImageView, as well as the x,y,h,w as a CGRect dimension frame.



+ (NSImageView *) getImage:(NSString *) image
                     frame:(CGRect) frame
{
    NSImageView *imageView = [[NSImageView alloc] init];
    [imageView setFrame:frame];
    [imageView setImage:[NSImage imageNamed:image]];
    [imageView setBoundsOrigin: NSZeroPoint];
    return imageView;
}


Below this function modifies the enumerated Window whilst passing in the frame (x,y, w, h dimensions), and the Screen which are passed in. It also specifies the window behaviour and background colour, which in this case it's an NSColor defined as a constant:



+ (NSWindow *) modifyWindow:(NSWindow *) window
                      frame:(NSRect) frame
                     screen:(NSScreen *) screen
{

    [window setBackgroundColor:t_colour];
    [window setCollectionBehavior:  
  NSWindowCollectionBehaviorStationary |
                                    NSWindowCollectionBehaviorCanJoinAllSpaces |
                                    NSWindowCollectionBehaviorFullScreenAuxiliary |
                                    NSWindowCollectionBehaviorTransient ];
    [window makeKeyAndOrderFront:NSApp];
    [window setAlphaValue:kConstAlphaDefault];
    [window setLevel:kCGMainMenuWindowLevel-1];
    [window toggleFullScreen:nil];
    return window;
}


When the NSScreens are enumerated, each member is sent as an argument screen, also idx number (which is redundant since we can simply get the screen index internally from the members of the class). Anyhow, we create an NSRect for the dimensions (x,y, height and width). Since we are interested in covering the entire space of said screen we use the size height and width, and start at 0, 0 (x,y). We finally affix an NSImageView with kConstImageBlock with is just a char constant defined in some header. This subview function was the first function we described in the first code snippet. Also there is a flag to detect the "primary" display. The NSImageView is only affixed as a subview on the "primary" display. The other displays just get a coloured in, however if you desire you can add the Image by removing the if then conditional, see below:



+ (void) displayBlockScreen:(NSScreen *) screen
                      index:(int) idx
{
    NSMutableArray* windows = [[NSMutableArray alloc] init];
    NSRect frame = NSMakeRect(0,
                              0,
                              [screen frame].size.width,
                              [screen frame].size.height);
    NSWindow *window  = [[NSWindow alloc] initWithContentRect
frame styleMask: NSWindowStyleMaskBorderless backing: NSBackingStoreBuffered defer: NO screen: screen];
    
    if (screen == [NSScreen mainScreen])
    {
        NSImageView *imageView = [self getImage:kConstImageBlock frame:frame];
        [window.contentView addSubview:imageView];
    }
    [windows addObject:[self modifyWindow:window
                                    frame:frame
                                   screen:screen]];
}


Last but certainly not least is the very first, entry point function which does exactly what it's name indicates, displayEnum. It sequentially enumerates thru all of the detected NSScreen screens value array, starting at index 0, and accounting for each of the Monitor Screen Displays that are found. The "do while" loop can be a "for next" loop or a bunch of other iterator types, but "do while" was on my mind, and was feeling adventurous. The loop stops incrementing the index as the array count is finally reached and the condition is met, see below:


+ (voiddisplayEnum
{
    int idx = 0;
    NSArray *screens = [NSScreen screens];
    NSUInteger count = [screens count];
    
    NSLog(@"\n\tTotal Screens: [%lu]\n\n", count);
    
    do {
        NSScreen *screen = [screens objectAtIndex:idx];
        [self displayBlockScreen:screen
                           index:idx];
        idx++;
    while (idx < count);
}


Obliged you chose to read thru this, and visiting my ghetto coding blog.I sincerely hope that this code can be of some service to you, a software engineer trying to dynamically generate full covering, always on top screen(s), with additional need for image subviews affixing to the respective detected window(s). Hopefully the code above can easily facilitate the need to detect multiple display configurations, as well as a designation of a "primary" display. Surely out there somewhere in the deepest recesses of this fine universe exists a use case scenario, imperatively requesting such specialised screen and window behaviour described above? I'm quite confident that the practical application exists somewhere in the vast macOS user world obusiness, corporate, healtheducation, maybe even cyber-security. 

Cheers & until next time,

-Apollo

Monday, September 9, 2019

Overriding OnPossess() with Unreal Engine 4.23.0

Recently Possess() has been deprecated from UE4, and when writing classes based on AAIController you have to use the function OnPossess().  When using the former vs the latter, you will have compilation problems, and potential breaks in the Artificial Intelligence for your various Pawns, and Blueprints, Blackboard, etc.


Above: AI Book I am currently reading. Quite insightful.


If you are using Blueprints, it's a matter of changing them. However you are using C++ code you must first do this in the header file (.h) of your class inheriting from AAIController:



 private: 

    UPROPERTY(transient)
    class UBlackboardComponent *BlackboardComp;
    
    UPROPERTY(transient)
    class UBehaviorTreeComponent *BehaviorComp;
   
 public:

   virtual void OnPossess(APawn *InPawn) override
  
    bool isDead = false;
    uint8 EnemyKeyID;
    uint8 PatrolKeyID;
    uint8 EnemyModeBBKeyID;
    uint8 isDeadBBKeyID;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MoveEnemy")


Then in the implementation file (.cpp) file you implement like this:



 void AEnemyAI::OnPossess(APawn *InPawn) {
    Super::OnPossess(InPawn);
    AEnemyCharacter *Char = Cast<AEnemyCharacter>(InPawn);
    
    if (Char && Char->Enemy) {
        BlackboardComp->InitializeBlackboard(*Char->Enemy->BlackboardAsset);
        EnemyKeyID = BlackboardComp->GetKeyID("Target");
        PatrolKeyID = BlackboardComp->GetKeyID("PatrolTarget");
        EnemyModeBBKeyID = BlackboardComp->GetKeyID("EnemyModeBB");
        isDeadBBKeyID = BlackboardComp->GetKeyID("isEnemyDeadBB");
        tChar = Char;
        BehaviorComp->StartTree(*Char->Enemy);
    }
 }

Friday, January 4, 2019

How to show FPS in Unity3D C#

Showing FPS can be helpful when you’re on a handheld device and gauging performance.

Sometimes you may need to throttle quality for device depending on the performance.

This code is how you display FPS in C# for a mono behaviour script.


  1. void Update () {
  2. deltaTime += (Time.deltaTime - deltaTime) * 0.1f;
  3. float fps = 1.0f / deltaTime;
  4. Debug.Log(Mathf.Ceil(fps).ToString() + “ FPS”);
  5. }

Tuesday, October 24, 2017

Showing a Cocoa UI Alert Panel in pure C

You can display an AlertPanel even if you have a strictly command line app. In the example below it shows a NSPanel called from pure C.


    id app = NULL;

    id pool = (id)objc_getClass("NSAutoreleasePool");

    if (!pool)
    {
        return -1;
    }
    pool = objc_msgSend(pool, sel_registerName("alloc"));
    if (!pool)
    {
        return -1;
    }
    pool = objc_msgSend(pool, sel_registerName("init"));

    app = objc_msgSend((id)objc_getClass("NSApplication"),

                       sel_registerName("sharedApplication"));

    NSRunAlertPanel(CFSTR("Test"),

                    CFSTR("Your App is running!"),
                    CFSTR("Ok"), NULL, NULL);
    
    objc_msgSend(pool, sel_registerName("release"));

Friday, September 23, 2016

Linear Interpolation (LERP) with C++ and Unreal Engine 4.13.0


In Unreal Engine 4 you will eventually need Linear Interpolation between two values to do something like ping pong between two float values across Time Delta. I wrote a "ghetto" function that does this and takes the arguments min, max, factor (scale), and then the value itself, which it increments/decrements accordingly. You can also do this with trig functions across Delta Time to achieve a similar effect. You can always get Delta Time from the Overridable Tick Method.

Here is the code:

float GameHelper::IncrementLerp(float x, float v) {
    return v+=x;
}

float GameHelper::xLerp (float mMin, float mMax, float mFactor, float value) {
    if (value>=mMin && goBackwards){
        value = IncrementLerp(-mFactor,value);
        if (value<=mMin) {
            goForwards = true;
            goBackwards = false;
        }
    } else if (goForwards && value<=mMax) {
        value = IncrementLerp(mFactor,value);
        if (value>=mMax) {
            goBackwards = true;
            goForwards = false;
        }
    }
    return value;
}

I use it for sky lighting in a game I am working on. The sky light appears to be pulsating from 0.7f to 2.7f intensity. I use this function and expose other functions in Blueprints. HD demo of my latest game, Jumper utilizing the pulsating::



Monday, September 19, 2016

Get an ENUM value from an Enemy AI Behaviour Tree in Unreal Engine 4.13.0 using C++

Often we intermingle C++ and Blueprints, and need for the two to communicate. With Behavior Trees, using ENUMs is an everyday occurrence and on occasion we need to access said values in C++ Code. Below a Service I created called Check For Player which overrides base UBTService, uses the TickNode to check for the existence of a Player that the EnemyAI sees.

See below:


void UBTService_CheckForPlayer::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
AEnemyAI *EnemyPC = Cast<AEnemyAI>(OwnerComp.GetAIOwner());

if ( EnemyPC) {
        AJumperCharacter *Enemy = Cast<AJumperCharacter>(GetWorld()->GetFirstPlayerController()->GetPawn());
        if (!Enemy) {
            return;
        } else if (Enemy && EnemyPC->tChar->EnemyLife>0) {
                OwnerComp.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Object>(EnemyPC->PatrolKeyID,EnemyPC);
                OwnerComp.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Object>(EnemyPC->EnemyKeyID,Enemy);
        }
        uint8 EnemyMode = OwnerComp.GetBlackboardComponent()->GetValueAsEnum("EnemyModeBB");
FString str = FString::FromInt(EnemyMode);
EnemyPC->tChar->SetMode(EnemyMode);
/*
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, str);
*/
}

}
My EnemyCharacter.cpp referenced above has different modes. Since I get an unsigned int8 from GetValueAsEnum("EnemyModeBB"), which is my enum variable in my BehaviourTree , I need to translate the uint8 to an ENUM on my EnemyCharacter class. This isn't necessary and you can case it out but since EnemyCharacter is my main class with all of the EnemyProperties, I want to send the information back.  See below:

void AEnemyCharacter::SetMode(uint8 m) {
    if (Mode!=EnemyMode::Hit)
        switch (m) {
            case 0:SetMode(EnemyMode::Attack);  break;
            case 1:SetMode(EnemyMode::Dead);  break;
            case 2:SetMode(EnemyMode::Flee);  break;
            case 3:SetMode(EnemyMode::Hit);  break;
            case 4:SetMode(EnemyMode::Idle);  break;
            case 5:SetMode(EnemyMode::Patrol);  break;
            case 6:SetMode(EnemyMode::Pursue);  break;
            case 7:SetMode(EnemyMode::Talk);  break;
            case 8:SetMode(EnemyMode::Taunt);  break;
            default:SetMode(EnemyMode::Pursue);  break;
break;
        }

}


Here is the definition of EnemyMode in EnemyCharacter.cpp class:

UENUM(BlueprintType)
enum class EnemyMode : uint8
{
    Attack      UMETA(DisplayName="Attack"),
    Dead        UMETA(DisplayName="Dead"),
    Flee        UMETA(DisplayName="Flee"),
    Hit         UMETA(DisplayName="Hit"),
    Idle        UMETA(DisplayName="Idle"),
    Patrol      UMETA(DisplayName="Patrol"),
    Pursue      UMETA(DisplayName="Pursue"),
    Talk        UMETA(DisplayName="Talk"),
    Taunt       UMETA(DisplayName="Taunt")

};

Also, here is a screenshot for the ENUM:


The variable definition in my BehaviourTree BlackBoard (zombieBB):


Wednesday, June 15, 2016

Custom Font(s) for TextView in Android (Java)

Using customized fonts in Android OS is not supported by default. You have to essentially put your fonts in an assets folder in TTF or OTF format, then reference it in an extended widget of EditText/TextView or whichever widget you'd want to use.

First copy your ttf to your /assets/ directory in your project root.

The next thing you need to do is create a helper class, mine is called TextViewHelper.java ->

package com.yourdomain.yourapp.helper;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
import com.yourdomain.yourapp.R;

public class TextViewHelper extends TextView {
    private static final String TAG = "TextViewHelper";
    private static final String fontname = "SourceSansPro-Semibold.ttf";

    public TextViewHelper(Context context) {
        super(context);
    }

    public TextViewHelper(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public TextViewHelper(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setCustomFont(context, attrs);
    }

    private void setCustomFont(Context ctx, AttributeSet attrs) {
        TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewHelper);
        String customFont = a.getString(R.styleable.TextViewHelper_customFont);
        setCustomFont(ctx);
        a.recycle();
    }
    /* force custom font */
    public boolean setCustomFont(Context ctx) {
        Typeface tf = null;
        try {
        tf = Typeface.createFromAsset(ctx.getAssets(), fontname);  
        } catch (Exception e) {
            Log.e(TAG, "Could not get typeface: "+e.getMessage());
            return false;
        }

        setTypeface(tf);  
        return true;
    }

    public boolean setCustomFont(Context ctx, String asset) {
        Typeface tf = null;
        try {
        tf = Typeface.createFromAsset(ctx.getAssets(), asset);  
        } catch (Exception e) {
            Log.e(TAG, "Could not get typeface: "+e.getMessage());
            return false;
        }

        setTypeface(tf);  
        return true;
    }

}

Mine forces a custom font programmatically. Though there are many ways to skin this cat, this way I am assuming all fonts need to be the same, and I am using only one. You could theoretically expose and use numerous fonts instead of just one, but this simply does only one, SourceSansPro-Semibold.ttf.

The next and final step is you have to reference it from your layout.xml(s). See below sample:

Wherever you have <TextView /> tags referenced change it to:

            <com.yourdomain.yourapp.helper.TextViewHelper
                android:id="@+id/hm_vpn_txt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_alignParentLeft="true"
                android:textColor="@color/test_color"
                android:textSize="16sp"
                android:text="@string/yourstring" />

And voila! You have custom fonts.

Generating "Always On Top" NSWindow in macOS across all detected displays

Also: Using UIKit & Cocoa Frameworks using Objective-C In m acOS or OS X , written in either Objective-C or Swift  Langues, you m...