I've a question about the libgdx Skin behavior.
the game I'm developing has a global AssetsManager (from the libgdx suite) that every class can access.
I load different TextureAtlas inside this assets manage
I know that assetManager.dispose() disposes all the resources loaded inside the assets manager.
Now, I would like also to have a Skin (for the GUI) loaded inside the assets manager.
The skin is gonna use several TextureAtlas...
Here's the question: since I'm gonna use skin.addRegion() and since the online API reference about the skin class says "The atlas will not be automatically disposed when the skin is disposed" is it a good idea to load all the TextureAtlasof the skin in the global assets manager?
I'm fearing about the dispose action. Because when I call the assetManager.dispose() both the TextureAtlas and the Skin will be called on the dispose method...but what if the TextureAtlas are disposed before the skin?
Could actually happen any problem about it?
The skin behavior is not so well-defined, I mean...what does the dispose method do?
Thank in advance,
Luca
skin.dispose() calls dispose on any specific resources that are Disposable. But the TextureAtlas itself is not one of the "resources" so it must be manually disposed of separately from the skin.
The only example of a disposable skin resource I can think of is a BitmapFont that does not use the TextureAtlas that you're using with the Skin.
Note that you should never call dispose on something that you loaded with the AssetManager. Instead, you should call manager.unload() on that resource so the AssetManager can properly manage dependencies.
The nice thing about manager.unload() is that it keeps track of how many other resources are dependent on the object and only disposes it when it's clear of dependencies. So if you also load your Skin with the AssetManager, you only ever need to worry about calling manager.unload("mySkin") and it will correctly determine whether the associated TextureAtlas should also be disposed.
But be sure to only call unload() on a resource once per time you called load() on the same resource. AssetManager's internal dependency counting does rely on all your load() and unload() calls mirroring each other one-to-one.
I didn't want to post an anwser but I wasn't able to post a comment with code -_-.
Ok, so if the situtation is this below:
`
assetManager.load("images/guiTextureAtlas", TextureAtlas.class);
assetsManager.load("skin/uiSkin.json", Skin.class)";
assetsManager.finishLoading();
Skin uiSkin = assetManager.get("skin/uiSkin.json");
uiSkin.addRegion(assetManager.get("images/guiTextureAtlas");
`
Is it all fine if I call assetManager.dispose() for disposing all the resources?
Related
I want to create a controller based JavaFX GUI consisting of multiple controllers.
The task I can't accomplish is to pass parameters from one Scene to another AND back.
Or in other words:
The MainController loads SubController's fxml, passes an object to SubController, switches the scene. There shall not be two open windows.
After it's work is done, the SubController shall then switch the scene back to the MainController and pass some object back.
This is where I fail.
This question is very similar to this one but still unanswered. Passing Parameters JavaFX FXML
It was also mentioned in the comments:
"This work when you pass parameter from first controller to second but how to pass parameter from second to first controller,i mean after first.fxml was loaded.
– Xlint Xms Sep 18 '17 at 23:15"
I used the first approach in the top answer of that thread.
Does anyone have a clue how to achieve this without external libs?
There are numerous ways to do this.
Here is one solution, which passes a Consumer to another controller. The other controller can invoke the consumer to accept the result once it has completed its work. The sample is based on the example code from an answer to the question that you linked.
public Stage showCustomerDialog(Customer customer) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
Stage stage = new Stage(StageStyle.DECORATED);
stage.setScene(
new Scene(
(Pane) loader.load()
)
);
Consumer<CustomerInteractionResult> onComplete = result -> {
// update main screen based upon result.
};
CustomerDialogController controller =
loader.<CustomerDialogController>getController();
controller.initData(customer, onComplete);
stage.show();
return stage;
}
...
class CustomerDialogController() {
#FXML private Label customerName;
private Consumer<CustomerInteractionResult> onComplete
void initialize() {}
void initData(Customer customer, Consumer<CustomerInteractionResult> onComplete) {
customerName.setText(customer.getName());
this.onComplete = onComplete;
}
#FXML
void onSomeInteractionLikeCloseDialog(ActionEvent event) {
onComplete.accept(new CustomerInteractionResult(someDataGatheredByDialog));
}
}
Another way to do this is to add a result property to the controller of the dialog screen and interested invokers could listen to or retrieve the result property. A result property is how the in-built JavaFX dialogs work, so you would be essentially imitating some of that functionality.
If you have a lot of this passing back and forth stuff going on, a shared dependency injection model based on something like Gluon Ignite, might assist you.
I've used AfterBurner.fx for dependency injection, which is very slick and powerful as long as you follow the conventions. It's not necessarily an external lib if you just copy the 3 classes into your structure. Although you do need the javax Inject jar, so I guess it is an eternal reference.
Alternately, if you have a central "screen" from which most of your application branches out you could use property binding probably within a singleton pattern. There are some good articles on using singleton in JavaFX, like this one. I did that for a small application that works really great, but defining all of those bindings can get out of hand if there are a lot of properties.
To pass data back, the best approach is probably to fire custom Events, which the parent controller subscribes to with Node::addEventHandler. See How to emit and handle custom events? for context.
In complex cases when the two controllers have no reference to each other, a Event Bus as #jewelsea mentioned is the superior option.
For overall architecture, this Reddit comment provides some good detail: https://www.reddit.com/r/java/comments/7c4vhv/are_there_any_canonical_javafx_design_patterns/dpnsedh/
I'm creating a simple game to learn Flash programming. To have a clean model/view separation, I want to create a Player class which simply holds data relevant to the user. I'm also creating a StatusView class which extends MovieClip and which coresponds to a movie clip symbol which I've created in my Flash project. Basically the StatusView will display the data of my Player class onscreen.
I'm used to doing this sort of thing using listeners, so I've found the EventDispatcher class and added one as a member of my Player class. I'd like to have my StatusView movie clip add an event listener to my Player class so that it can receive messages whenever I change the data in my Player class.
The problem is, there doesn't seem to be anywhere for me to put my Player class so that the StatusView can find it (to add the listener). Everything in the project is created directly by one of the movie clips, and the runtime seems to create these movie clips in an arbitrary order. For example, say I create a MovieClip symbol called GameView and I create the instance of the Player there, and GameView is the parent of StatusView. When StatusView is constructed, I'd like to be able to access the Player from it's parent, but at that point GameView hasn't had it's constructor code run yet. This is true even if I wait for the ADDED_TO_STAGE event.
I could put the game model code in a singleton, but this seems like a hack to me. Is there a best practices way in Flash that lets me create and access my game model independent of all the MovieClip symbol stuff?
If you want to pass the reference of the Model to the constructor of the View, but are not calling the constructor yourself (because you do not create the object via code) you are out of luck here.
You could instead simply define a method on your View to pass a reference of the Model object:
public function setModel(value:Model):void
usage:
view.setModel(player);
There's no "law" that you have to pass the Model to the constructor of the View.
You can also create a set function for convenience:
public function set model(value:Model):void
usage:
view.model = player;
I feel like I have to disagree on the Singleton. The purpose of a Singleton is to guarantee that there's only one instance of it in existence. That's it.
It is not there to pass reference around easily (because the method to get the single instance is static). This is (IMO) a bad practice.
You could make anythign static in order to pass it around "easily". But this would make a mess and nobody does that.
But suddenly, just because the singleton pattern uses a static method, a lot of people think it's a clever way to get to the reference. I beg to differ.
First of all, you could implement Player class as singleton if you need just one instance. I don't think that that looks like a hack (for example, in PureMVC framework each model is a singleton).
At second, you can create instances of Player class in some general class (manager) and send them to views.
P.S. Also, I want to note that you can extend your Player class from EventDisptacher without creating specific field "eventDispatcher" in Player class. I don't know what way is better, but this one is simpler, imho.
I have an application which pulls in Bitmap resources from a server - currently I use the Loader class to do this, then, once they're loaded, generate a BitmapData based on the loader dimensions and draw the instance of Loader directly to it (the BitmapData is used for Away3D textures as well as Bitmap instances, so I have no need for the Loader once fetched).
This has always worked for me, but recently I started getting 0x0 Loaders, and invalid BitmapData as a result.
I stopped doing this:
this.imageBitmap = new BitmapData(this.imageLoader.width, this.imageLoader.height, true, 0);
..and started doing this:
this.imageBitmap = new BitmapData(event.target.content.width, event.target.content.height, true, 0);
Where event is the Event.COMPLETE event fired by the loader. This fixed the dimension problem, but the BitmapData is just a plain white bitmap (and it's set to transparent by default, so this is being drawn into it). Frustratingly, this doesn't happen every time, if I refresh the application it works as it should around 25% of the time, otherwise it plays up like this.
I've got a tight deadline and I'm really screwing about this, if anyone could help or suggest a better way of doing it you'd really be saving my neck!
Sounds like you need to adjust the image decoding policy for the loader - to ensure it decodes the image before COMPLETE fires - then the width and height etc should be reliable.
To do it, just add a suitable LoaderContext object to the Loader.load method:
var loaderContext:LoaderContext = new LoaderContext();
//set decode policy
loaderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;
//load image
loader.load(yourUrl, loaderContext);
The default decode policy is ImageDecodingPolicy.ON_DEMAND - which doesnt decode the image until it is actually required.
Lang docs: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/ImageDecodingPolicy.html
Fixed it, stupid oversight and bit of an obscure situation but I'll leave an answer in case anyone runs into something similar.
My loader is contained in an Asset class - when another object requires the internal bitmap, it queries this class - if the bitmap's present, it returns it, if not it loads it with a loader and registers a callback for a COMPLETE event which is fired when the Loader has loaded and transferred its contents to a BitmapData instance.
The stupid mistake I'd made was that, if several objects were querying the same (as-yet-unloaded) asset, it would start reloading the asset each time, creating a new Loader as it did so...so when the first Loader was complete, it would fire an event but no reference to it would exist, not only creating a memory leak but causing the Asset class to extract the BitmapData from the most-recently-created Loader, which was not complete! The asynchronous nature of Loader is the reason it worked sometimes, as on occasion the final Loader would be ready in time for BitmapData extraction.
Simple solution was to create an internal boolean, _isLoading, which is set to true the first time load() is called - any subsequent calls are ignored if it's true, but callbacks still registered, works a treat!
I am trying to use BulkLoader (https://github.com/arthur-debert/BulkLoader) to preload all assets of my AS3/Flex application. Right now it is working and I am able to access the contents everywhere on my Main module (where my BulkLoader instance lives).
My problem: I need to handle the BulkLoader.COMPLETE event from my preloader (pre.as living next to Main.mxml on src/), to allow the user to exit the preloader and enter the application ONLY after BulkLoader.COMPLETE was fired.
Thanks!
Why not pass the reference to the BulkLoader instance?
Somethinglike this:
preloader.setLoader(_bulkLoaderInstance or name)
or
var preloader:Preloader = new Preloder(_bulkLoaderInstance or name)
BTW, the LoaderMax from Greensock is better (fewer bugs, more reliable events, nicer API).
My AS3 application basically does the following (pseudo code from main application class) 3 or 4 times by adding custom objects to stage:
_movieClipClassVariable = new MyCustomSpriteSubclass();
_movieClipClassVariable.addEventListener(MyEvents.READY, function(event:Event):void {
_hideLoading();
mcHolder.addChild(_movieClipClassVariable);
});
_movieClipClassVariable.addEventListener(MouseEvent.CLICK, myClickHandler);
private function coverClickHandler(event:Event):void
{
...
}
What is the right way to allow Garbage Collector to recycle _movieClipClassVariable after it is not necessary? Assign null to it? Remove all listeners? Use weak reference for listeners?
Thanks in advance!
I would say all of the above.
I recommend reading Grant Skinners articles of Resource Management. Also take a look at his slides from his Resource management talk.
There is quite a lot of information out there on this subject, and those two links are the best resources I have found.
In order to get use of garbage collector you should consider:
Not defining handler methods inside the X.addEventListener() call
Remove all event listeners on the object you want to free up from memory
Make the object null
4.(optional) you can force garbage collector calling system.gc();