How to trigger on_draw method in gtkmm 3.0 for a DrawingArea object - cairo

Using gtkmm 3.0, in a Gtk::Window object I have an object of a self defined class derived from the Gtk::DrawingArea named Anzeige.
#include <gtkmm/drawingarea.h>
class Anzeige : public Gtk::DrawingArea
{
public:
Anzeige();
virtual ~Anzeige();
private:
//Override default signal handler:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
void zeigeTemp(const Cairo::RefPtr<Cairo::Context>& cr, float t_IST, float t_SOLL, int x, int y);
//member data
//...//
float t_Elt_IST;
float t_Elt_SOLL;
};
An override function of the on_draw method is there and gets a Cairo::Context as a parameter named cr. In the function definition of this on_draw override, I successfully make use of cr to show a bitmap and some pango layouts. The function zeigeTemp shows a pango layout at position x and y. zeigeTemp is called in the on_draw function and gets the same Cairo::Context cr.
When values are updated in my program, I want to call either the on_draw method or zeigeTemp manually, just so the screen is up to date. But in order to call the methods, I need to pass the Cairo::Context to them.
I do not make explicit use of the Cairo::Context anywhere else in my code by now. The on_draw method is called by the program magically by itself and some Cairo::Context is used for it.
Is there an easier way to tell Gtk to redraw a DrawingArea without having to specify a Cairo::Context? When I click in the DrawingArea it is redrawn without additional input. So there must be a way to make Gtk do this on command. Which command is it?
When I try to extract the Cairo::Context from the Gtk::Window with the create_cairo_context method I get a segmentation fault error on runtime. I do not understand, when Gtk uses a Cairo::Context by itself and when I need to create it to pass it to for example the method zeigeTemp.

I searched for "redraw" on https://developer-old.gnome.org/gtkmm/stable/classGtk_1_1DrawingArea.html and found this paragraph:
You can also force a redraw by adding to the “damage region” of the drawing area’s window using Gtk::Widget::queue_draw_region(), Gtk::Widget::queue_draw_area() or Gtk::Widget::queue_draw().

Related

Call function from a premade script in Unity

How do I call a function from a Unity (XR Interaction Toolkit) script that's appended to a Ray Interactor? Precisely what I have is a GameObject made as an XR Ray Interactor and appended the XR Direct Interactor script. I want to call the function GetValidTargets from that script to see with what GameObject it targets. How do I call this function in another script? I already have the GameObject specified and tried different methods to implement it, for example GetComponent<>().
This is what the function says in the script so that comes after I call it.
/// Retrieve the list of interactables that this interactor could possibly interact with this frame.
/// This list is sorted by priority (in this case distance).
/// <param name="validTargets">Populated List of interactables that are valid for selection or hover.</param>
public override void GetValidTargets(List<XRBaseInteractable> validTargets)
How do I call this function?
Calling the function if you want to call the function, append the XRBaseInteractable component to every GameObject that you want to able to hover or interact with. Create a List (which are in the System.Collections.Generic namespace), add each XRBaseInteractable instance to it and pass it in to the GetValidTargets() function.
GameObject[] interactableObjects; // Set in inspector or somewhere in code
List<XRBaseInteractable> interactables = new List<XRBaseInteractable>();
foreach(GameObject interactableObject in interactableObjects)
{
interactables.Add(interactableObject.GetComponent<XRBaseInteractable>());
}
GetComponent<XRDirectInteractor>().GetValidTargets(interactables);

How do you add a button event to a button via script with parameters included Unity?

I am trying to add an onClick event to a bunch of buttons on screen that I have Instantiated. But the function I am calling needs parameters. When I put the parameters the code doesn’t run but when I don’t it runs but the function doesn’t do what it is supposed to because it doesn’t have the right parameters. Any ideas?
public void PreviewButtonLook(Image previewPart, Sprite previewSprite)
{
previewPart.GetComponent<Image>().sprite = previewSprite;
}
button.GetComponent<Button>().onClick.AddListener(PreviewButtonLook(previewPart, options[i]);
onClick.AddListener() accepts a delegate of zero parameters.
You can create a zero-parameter anonymous function and pass it as a delegate.
This zero parameter anonymous function can call another function and pass it as many parameters as you want.
button.GetComponent<Button>().onClick.AddListener(delegate {
PreviewButtonLook(previewPart, options[i]);
});
But be aware of function closure.

Function with vector parameter not shown in OnDelta Editor // Unity 2019.2.6f1

I´m using the Lean Touch+ Asset to implement drag and drop for 3D objects. Unfortunately the needed function is not showing up in the OnDelta() event editor.
The example is working, but showing in the event editor. Also I tried an older 2018 unity version and there it works fine. Anyway I´d like to use the newer one.
If I change the Vector2 to a float, it gets listed in the editor, but Vector2 should work as well or am I wrong?
This code is not complete, because it´s not mine and I´m not sure if I can just share it. But I hope it helps understanding my problem.
using UnityEngine;
namespace Lean.Touch
{
[HelpURL(LeanTouch.PlusHelpUrlPrefix + "LeanManualTranslate")]
[AddComponentMenu(LeanTouch.ComponentPathPrefix + "Manual Translate")]
public class LeanManualTranslate : MonoBehaviour
{
public void TranslateAB(Vector2 magnitude)
{
Translate(DirectionA * magnitude.x + DirectionB * magnitude.y);
}
There are basically two types of callbacks for UnityEvent
Static
Static calls are preconfigured calls, with preconfigured values that are set in the UI. This means that when the callback is invoked, the target function is invoked with the argument that has been entered into the UI.
Dynamic
Dynamic calls are invoked using an argument that is sent from code, and this is bound to the type of UnityEvent that is being invoked. The UI filters the callbacks and only shows the dynamic calls that are valid for the UnityEvent.
UI refers to the Inspector in the Unty Editor here.
BUT .. unfortunately there is a Bug in newer versions so dynamic parameters do not work with UnityEvent currently.
(Fixed in 2019.3 and 2020.1 ... don't use those though as the are still in Alpha & Beta state!)
In general Vector2 was afaik never a parameter to be displayed and edited via the Inspector when choosing a static callback type and was only applicable for passing it to a dynamic callback.
Only the basic types like int, string, float, bool and Object references work for the static ones.
As a workaround you can still add callbacks on runtime via script - though it is kind of shitty and only makes sense if the target component sits on the same GameObject as the one with the UnityEvent
public class LeanManualTranslate : MonoBehaviour
{
private void Awake()
{
GetComponent<LeanMultiSet>().OnDelta.AddCallback(TranslateAB);
}
private void TranslateAB(Vector2 magnitude)
{
Translate(DirectionA * magnitude.x + DirectionB * magnitude.y);
}
}
Or alternatively stick with 2019.1.14 where it works as well. There bug seems to be introduced since 2019.2

Issue having a particular SKAction to fire in a sequence

I'm sure this is a thread issue but I can't figure it out.
I want to make a sprite fade and reappear somewhere else. I can get it working one way, but not the other (see below) The sequence I want is:
fade, x, y, z (all are SKActions)
One of my classes provides the implementation details for the warp in animation (adhering to a Warpable protocol I created)
protocol Warpable
{
func warpOutAnimation() -> SKAction
}
//and then elsewhere, in my actual class:
func warpOutAnimation() -> SKAction
{
return SKAction.fadeInWithDuration(1.0)
}
So here is my sequence within the game:
myNode.runAction(SKAction.sequence([SKAction.fadeInWithDuration(1.0), x, y, z]))
This runs perfectly fine. All good.
Now, if I wanted to instead grab the warp implementation from the class (since this is dynamic from a factory class I have):
myNode.runAction(SKAction.sequence([
(self.currentMonster as! Warpable).warpOutAnimation(), x, y, z]))
This sequence does not execute the warpOutAnimation (despite it returning an SKAction) but it does fire x, y, z still.
currentMonster is instantiated from a factory based on some context within my game. I have a breakpoint there, and it does indeed hit the protocol's function to fire, but the SKAction isn't run.
Any ideas why this would happen? Even if I put the warp function right above where I'm doing the sequencing it doesn't do anything. Thanks so much.
As per docs, the fadeInWithDuration action changes the alpha property of the node from its current value to 1.0.
This action has no effect if alpha value of a node is already 1.0, and that is probably your issue.
What you probably want is, to use fadeOutWithDuration, to make a node disappear, before you try to use fadeInWithDuration method to make it re-appear.
So, make sure that myNode has alpha < 1.0 if you want to apply fadeIn action.
This function seems to be missing a return statement. It would not compile so I presume that something is missing from your sample code.
func warpOutAnimation() -> SKAction
{
SKAction.fadeInWithDuration(1.0)
}

c and objective-c variables

Let me see if I can articulate what I'm trying to do... I'll distill it to the core issue.
I have an objective-c program and a c callback function. The context is I am using cocos2d and chipmunk physics with the iphone sdk. What I am trying to do is update "score" upon a collision between a bullet and a monster. Everything works fine except for updating the score.
the game logic is in obj-c but the actual collision logic is done in a c function that gets called when things collide. For example, it is there that I render the flames/explosion of the collision. It is also there that I want to update the score.
Here's the problem:
But score is an instance variable of the "GAME" object and I do not have visibility into that instance variable. I suppose I can pass into the c function another parameter by reference called &addscore or something, but was wondering if there is a more obvious way to do it since there might be a bunch of other variables beyond 'score' that must be updated upon the collission.
the net is I need variables in the object to be seen by the c function, and vice versa: those variables set in the function to be seen in the object.
thanks in advance.
Your knowledge and thoughts about gaining access to Obj-C instance variables within C code by passing them by reference seems correct.
If you need to pass a number of variables I assume they collectively make up some kind of "game state" description. Perhaps these could be grouped into a seperate object or structure and passed into the C function via a single parameter?
As an example, the following class:
typedef struct GameState {
int score;
int numberOfBulletsLeft;
} GameState;
#interface GAME : NSObject {
GameState state;
}
...
#end
Would work well with a C function such as the following
void myCFunctionThatDoesCollisiondetectionEtc(GameState * state) {
NSLog(#"You have %d bullets left", state->numberOfBulletsLeft);
}
If your existing GAME object has suitable properties or messages, you may even be able to do something like the following, where you simply pass your entire Objective-C object:
void myCFunctionThatDoesCollisionDetectionEtc(GAME * myGame) {
if (...)
[myGame increaseScore:50];
else
[myGame decreaseScore:50];
}
A third alternative would be to change the return value of your C function to indicate if a collision has been detected and then leave it up to the Objective-C code within the GAME class to update the score and any other actions which may need to occur.
To improve on that last answer a bit more, you can do the following:
cpSpaceAddCollisionPairFunc( space, 1, 2, (cpCollFunc)functionName, game);
void functionName( cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, GameClass *game) {
[game doSomethingToScoreSomething];
}
No need to cast the pointer inside of the function, you can cast the function pointer instead. That's what I've done internally with the Chipmunk source and it's a lot cleaner.
No, you do not need variables in your object to be visible by the function. That breaks encapsulation, and it's a bad idea. When you want an object to do something (like changing some internal value such as the score) you should provide a method to accomplish that effect.
If you allow code outside your class to alter your instance variables, then you're throwing away a key advantage of object-oriented programming.
If the game object is a singleton you can access it from any scope (which includes your C callback). You would make a singleton if you only ever want one instance of some object to exist. A singleton can always be reached from anywhere by sending a message to the class to retrieve the singleton instance:
[Game sharedGameInstance];
Alternatively, chipmunk allows for you to pass a void * data to the callback. This is to accommodate the programmer to send information he needs to the callback.
You can send a pointer to your game object instance in that void * to the callback, like so:
cpSpaceAddCollisionPairFunc( space, 1, 2, &functionName, (void *)game );
void functionName( cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data ) {
GameClass * game = (GameClass *)data;
// do whatever you need here. You can call messages on game as per usual.
}