Is there such thing as a global variable? (GDscript) - variables

I'm trying to make a game but I need something like a global variable for it to work. Is there a way in GDscript that you can make a variable that works across all nodes with scripts. I need a button that makes you buy a gun which would set a variable to true and with that variable being true, you could equip the gun.
This question doesn't really fit this section where it says: What did you try and what were you expecting? so I'm just gonna skip it.

Is there a way in GDscript that you can make a variable that works across all nodes with scripts.
You could use an autoload.
Go to the Project menu, the Project Settings option, in the Autoloads tab… And there you can set a script, and give it a name. It will be available for every node in the scene tree.
For example, you can have a "globals.gd" script that looks like this:
extends Node
var has_gun := false
Then you make it an autoload with the name "Globals". So in any other script you can use it. For example:
extends Node
func _ready() -> void:
print(Globals.has_gun)
And yes, autoloads will stay there even if you change the current scene.
You might also be interested in the Signal bus (Event bus) pattern, which involves defining signals in an autoload, such that other scripts emit them or connect to them.
Technically the autoload is not a true global. As I said, the autoload will be available for the nodes in the scene tree.
This also means the autoload will not be available for a script that is not a Node (e.g. a Resource), or otherwise not in the scene tree.
Unless you use a hacky workaround to get a reference to the autoload, which I will not go into.
Instead, I will give you an alternative: resource based communication.
This time you create a "global_resource.gd" that look like this:
class_name GlobalResource
extends Resource
var has_gun := false
And then you can use the context menu on the FileSystem panel to create a new resource. When Godot asks you for the type, you select GlobalResource, and give it a name such as "globals.tres".
Then you can use it like this:
extends Node
const Globals := preload("res://globals.tres")
func _ready() -> void:
print(Globals.has_gun)
Everywhere you preload that same resource file ("globals.tres") you will get the same Resource instance. It does not matter if it is in the same scene, or if you changed the current scene.
And yes, this does not depend on the scene tree. And yes, you can put signals in there too.
For completeness sake, I'll also mention that there is another hacky workaround which involves defining a Dictionary or Array as const in a script with a class name. Since in Godot 3 const does not imply inmutable (don't count on this on Godot 4). That is how some people currently work around the lack of static variables. However, I believe you won't find it necessary.

Related

How can I refresh my composable when new data is being inserted?

My team and I have to make a license plate scanning app as a school project. With that, we have comments and pictures which can be added to cargo. Whenever the user scans a plate they also get the chance to change the checked info in case of a mistake. The problem is that whenever we delete data from the scanned plate it doesn't show on the screen that it has been deleted until we go to another screen. The same goes for the lazy column which we use for inserting new instances of comments and pictures. The data doesn't show on screen until we turn our screen or go back to another screen. private val pictureList = mutableListOf() is what we use for the pictures and for the text we use var countryCode by remember { mutableStateOf(CountryCodeText) }
var licenseNumber by remember { mutableStateOf(LicenseNumberText) }. pictureList is a global variable and the other ones are local variables which use global variables in the mutableStateOf. How can we make sure that the UI updates whenever the data changes? In advance I want to say thanks for the help! (Code is written in Kotlin and jetpack compose)
Just replace the mutableListOf() with a mutableStateListOf(...), and prefer to keep all the state logic confined to a ViewModel. The viewmodel should preferably be only one for the entire app, and the entire app should have only one activity.
The viewmodel should act as a single source of truth for the entire activity's UI state, while also handling all the updates to the UI efficiently.
The #Composables should only be incharge of displaying the state, and sending events to the viewmodel to update the state, for example, an onClick event may be sent up to the viewmodel by a button too trigger a state change in another part of the app.
Take this codelab to learn all about state in Compose (Well, not all, really, but good starter).
Also, changing screens destroys all the #Composables of the current screen, and so when you ce back there, all the #Composables are re-created, and the correct data is fetched. If you wish to trigger "recompositions" upon changing a variable, you must ensure that the concerned variable is a state-holder, i.e., initialized with one of the pre-built state initializers, like mutableStateOf(), or mutableStateMapOf, etc.
We usually have a mutableState*Of format for determining whether a pre-built state initializer is available. The most common ones are covered, obviously, but if not, you'll need to create a new type of initializer yourself, and if that is not something you know how to do, currently, you can just go about checking whether the type of data you wish to store is Immutable. If so, you can just wrap it in a mutableStateOf<DataType>() call, and it will trigger the recompositions. Know that this is not as efficient as pre-built initializers, but definitely gets the job done.
Also, I suggest you take the compose-pathway to get the basics down. It covers everything ranging from creating a simple UI using basic pre-built Layouts to creating a complex animation-driven application using custom Layouts.
So, definitely a lot to take it, but I hope you get there.
Happy composing,

Adding "properties" to objects in a Blender scene

I am just starting my dive into Blender coming mainly from Quake's Radiant. I am trying to research whether it will fit the need I have for a level editor replacement. So with that in mind, here is my question:
What is the best method for creating and storing a set of prefab "entity" objects such as health packs, ammo pickups, and "moveable" objects such that they have a set of "properties" that can be changed within Blender?
I have found this page, but I am still getting lost as to how to integrate them on a per object basis and achieve the desired result:
https://docs.blender.org/manual/en/dev/editors/properties_editor.html
Note: It is not my goal to use the Blender game engine - just attach values to things for me to export to my own engine.
Edit1: Found an article discussing the topic although it seems very outdated:
https://www.gamasutra.com/blogs/IwanGabovitch/20120524/171032/Using_Blender_3D_as_a_3d_map_editor_rather_than_programming_your_own_from_scratch.php
Example:
// entity 105
{
"inv_item" "2"
"inv_name" "#str_02917"
"classname" "item_medkit"
"name" "item_medkit_11"
"origin" "-150 2322 72"
"triggerFirst" "1"
"triggersize" "40"
"rotation" "0.224951 0.97437 0 -0.97437 0.224951 0 0 0 1"
}
While we can manually add custom properties to any object, these are added to the specific object so can be unique to each object.
A better way of integrating new properties is to use bpy.props, these can be added to an objects class in blender, this means every object will have the same properties available.
You can setup a custom panel to edit your properties, like this simple example. Both the properties and panel as well as your object exporter can be defined in an addon which you can have enable at startup so that it is available every time you run blender. An addon also makes it easier for you to share your game editor with others.
The link I found seems to be the best option and allow for the most flexibility. The source code for the Super Tux Kart plugins serve as a great reference implementation:
https://sourceforge.net/p/supertuxkart/code/HEAD/tree/media/trunk/blender_26/

How do I go to the nth method of the eclipse editor's file?

I need to write a function goToNthMethod(int n) to let the user jump to the nth method in the file being edited.
Ideas so far:
I imagine the ContentOutline reads its tree from some sort of IContentSource (made up) or something, if I can read from the same source, that would probably be cleaner. Does something like this exist?
Read the contents of the outline view, and maybe simulate a double click on one of the Outline view's entries. This is as far as I got before I realized I was in over my head:
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IViewPart part = page.findView("org.eclipse.ui.views.ContentOutline");
ContentOutline outline = (ContentOutline)part;
PageBook pageBook = outline.book; // Doesn't work, book is private
Tree root = pageBook.currentPage; // Doesn't work, currentPage is private
String label = root.getLabel(); // Nothing like getLabel exists
Read the entire IDocument's contents, parse the java source code within, get the offsets in the file, and feed that to the editor.selectAndReveal method. However, parsing the java source code within is a massive task, so this approach probably won't work.
Use outline.getCurrentPage(), which is a JavaOutlinePage, but I can't seem to import that class. I'm guessing I need to pull in the entire JDT project to do that. This approach also means I'm tied to a specific language, when I want my goToNthMethod to be language agnostic.
Any ideas on how I can jump to the nth method? Thanks!
Some context: I'm integrating Dragon NaturallySpeaking with eclipse to be able to program with my voice. It's working well so far, but one tedious part is navigating around the file, which would be made easier if I could say "go to 8th method". In fact, just "go to 8th entry" to just go to the 8th row in the outline view would be sufficient. Any other ideas appreciated!

AS2 AttachMovie from loaded swf movie

i'm facing one problem about attaching movieclip from loaded movie, so basically we have a Map
Map.loadMovie("SimpleMap.swf");
in this map there's a npc dialogue with its name "Dialogue1" I want to attach it to the client. It should be basically something like
_root.attachMovie("Map.Dialogue1", "dialogue", _root.getNextHighestDepth());
but it seems I can't get it to work. Anyone can help?
Note: Also I want to attach the movieclip to the client instead of the map, else I would use Map.attachMovie
it's been a while since I wrote any Actionscript 2 stuff, but have you tried removing the quotes around Map.Dialogue1 ? - If I remember correctly passing a string would make Flash look for the symbol in the library, not from the global or current scope...
_root.attachMovie(Map.Dialogue1, "dialogue", _root.getNextHighestDepth());
If you want you can import mx.core.UIObject and then use the method _root.createObject() (or if it is O-O use createClassObject()).
It is going to attach the "npc dialog" as an object... you need to specify the linkage name and give the instance a name. So for example if you called the dialog "npc_dialog" in the library then use:
_root.createObject("npc_dialog", "my_npc", _root.getNextHighestDepth());
Here is something else you can try... go to the library and drag a instance of the movie onto the stage somewhere where it will not be seen, like for instance on the next key frame or off the stage then try to run attachMovie().
What happens is flash will compile the clip in the most efficient way possible so if it sees you imported a package but did not use it then it will ignore this class in the compiled clip... so when you go to run and it tries to attach the movie it can't find it.

titanium how do i add a view to the single context

So i have a titanium app, and i just read about single contexts. (Incidentally, somebody here should write a book about programming in titanium... the only one out there doesn't really mention single contexts or any of that new-fangled stuff. Heck, make it an eBook. I'd buy it)
The titanium documentation stresses their use (http://docs.appcelerator.com/titanium/latest/#!/guide/Coding_Strategies-section-29004891_CodingStrategies-Executioncontexts) and then politely forgets how to implement a single context!!
So, question:
Let's say i have the awesomeWidget page - this just shows a button, and when you click on a button a new screen appears.
The aswesomeWidget page is accessed through another page - it is not from the root of the titanium app.
Keeping to single contexts, how do i add the view that the button creates to the current window?
Do I:
keep a global pointer to the current (and only) window?
pass the variable holding the current window down to all the following pages that use it
something else?
First off, Titanium keeps a reference to your current window anyway for you, so this use case is easy. For example:
awesomeWidgetButton.addEventListener('click' function(e) {
var yourView = Ti.UI.createView({...});
Titanium.UI.currentWindow.add(yourView);
});
If you want to dig further, the concept of a single context is closely tied to the use of CommonJS modules and the require keyword. It is very simple to keep a single context, just never open a window with the url component filled out, and liberally use the require() keyword. Other than that, its up to your imagination to keep track of who points to what and vice versa, there are standard patterns and best practices that apply here (MVC, Singletons, just keep it simple) just as in coding in any other language.