ParticleData's influencer's data
The current ParticleData has all data in a "raw" manner (all possible attributes that a particle can have, are already declared). If an influencer wants to store custom data, it can't, there is no much space to play with. On older versions, there was a Data Map, and the get/setData that allowed an influencer to store new data values. It would be great to have to have that option back (with a hashmap or an array of objects, like Spatial's controls), but lazily instantiated.
Comments (21)
-
repo owner -
reporter Yes, currently I was about to make an influencer. About the performance, that's why I suggest the lazy initialization, so it only affects the cases where it is used.
-
repo owner your option provides very slow access to the data, but I will think about what we can do for this :)
-
reporter I dont think a data map would be slow, at least with a custom fast-implementation. For example, the data declaration could be with:
int declareData();
And that int returned would be the data id to retrieve/set the data with:
<T> T getData(int dataId); void setData(int dataId, Objec dataValue);
So, internally, it could be a simple array when accessing/setting per frame:
Object[] values;
So, finally you would have something like:
private Object[] values; public int declareData() { values = <COPY_+1>; return values.length - 1; } public void setData(int dataId, Object dataValue) { values[dataId] = dataValue; } public <T> T getData(int dataId) { return values[dataId]; }
-
repo owner - changed status to resolved
I have added the API to the version 2.5.0 and updated implementation of ColorInfluencer to show how it works:
-
reporter Well, the problem with that implementation is that it isn't as fast as the one with the array (commented above). I can also see you aren't doing a lazy initialization (what makes sense if your objective is to modularize the full "raw" particle data. But again, what about perf?, wouldn't it be better the array alternative?. It is a little bit less "beautiful" but also have it advantages. It is not just performance, but also reusing the same name on another influencer. If two different persons implements two influencers and set the same name, those would clash if put together (and so, difficulting the share). What do you think about all that matter?
-
repo owner @NemesisMate where are you going to store the index of declaration?
-
reporter In the same place that you use the "name" of the data, in the influencer using it?
-
repo owner @NemesisMate I have re-implemented the custom data API again ;) you can use 2.6.3 version of the library. Examples: https://github.com/JavaSaBr/tonegodemitter/blob/master/src/main/java/tonegod/emitter/influencers/impl/ColorInfluencer.java https://github.com/JavaSaBr/tonegodemitter/blob/master/src/main/java/tonegod/emitter/influencers/impl/RadialVelocityInfluencer.java
-
reporter Well, the current implementation seems to be faster, but I can't fully understand why the need of a static "reserve" and a non-static one.
Having both is just over-complicating things. Without the non-static, it would work the same way (It would create always the full sized array for all static-reserved data). So, IMO, or there is a static-reservation (so every particleData will be ready/reserved for every available influencer) or a per-object reservation (so every data will be optimized for the current influencers being used). However, the current implementation is kind of weird or there is something I don't get.
Another thing to have in mind, is that the static implementation is very limiting. It is causing problems when using the same influencer multiples times on the same ParticleData.
My suggestion, so, is to just make a per-object reservation, just like the code I proposed (not statics), so you declare them when initializing the influencers.
-
reporter Another point I see that is overcomplicating the class itself, is separating the data per int, float and object. Now that I think, it would be even better if an influencer could only reserve 1 slot. Every influencer can create it data structure (maybe that implements InfluencerData) and this data structure is the one they use on the ParticleData. This particle data could even be passed on the influencer initializer method. For example:
class ColorInfluencerData implements InfluencerData { Color color1; Color color2; }
And so, in the influencer initializer:
class ColorInfluencer implements Influencer<ColorInfluencerData> { ... void initialize(ParticleData particleData, ColorInfluencerData influencerData) { } .... }
The particle data could even be removed from there (but maybe it is useful to access other influencers if present).
This way, the reservation on the ParticleData would be managed by the particle emitter (the one that has the influencers) and forces the implementing developer to use it in a more standard and easy to understand manner, avoiding too miss-conceptions without sacrificing in terms or efficiency (it allows even for more control: the data array size would be much more limited, for example).
-
reporter - changed status to open
Changes suggested
-
repo owner @NemesisMate how your implementation will work in the case when we change the list of influencers on runtime for a particle emitter?
-
repo owner @NemesisMate
"Another point I see that is overcomplicating the class itself, is separating the data per int, float and object"
have you seen my examples? I used data classes there.
-
repo owner @NemesisMate
"Another thing to have in mind, is that the static implementation is very limiting. It is causing problems when using the same influencer multiples times on the same ParticleData." any examples of these problems? I don't think so.
-
reporter "how your implementation will work in the case when we change the list of influencers on runtime for a particle emitter?" It will just work, it doesn't change anything if the influencers are changed at runtime or not.
"ave you seen my examples? I used data classes there." Yes, I've seen the examples. What I meant is the class itself, not the usage of it (but anyway, the InfluenceData proposal is even simpler to use)
"any examples of these problems? I don't think so." Well, looking at the code, if you set two ColorInfluencer to the same particledata, they will both override the same ParticleData Id, as they are using a static reserved id.
-
repo owner @NemesisMate
"Another thing to have in mind, is that the static implementation is very limiting. It is causing problems when using the same influencer multiples times on the same ParticleData." Hm, then I think my understanding of your implementation is wrong :(
"Well, looking at the code, if you set two ColorInfluencer to the same particledata, they will both override the same ParticleData Id, as they are using a static reserved id." Are you sure that it is valid use-case? because it can't work at all.
-
reporter Well, It depend on the influencer. For the current color influencers it may not work, but for a direction influencer, for example, you could want to add multiple ones (as if you were giving different forces). I think that while for all current influencers it would not make a lot of sense, maybe it would allow more influencer types (conditional influencers?). Maybe there could be some influencers where you want something to happen based on the current time of emission, so you would have a new way of configuration (eg: InfluencerByTime, an influencer that activates one or other sub-influencers based on the time of the emission. It could have, for example, 3 sub-influencers of the color type, and based on the time, it would activate one or the other).
-
repo owner @NemesisMate I see..., but I still don't understand your implementation, so I will continue to think about a new implementation for your requirements.
-
reporter The implementation isn't that hard. A working implementation is the posted above:
private Object[] values; public int declareData() { values = <COPY_+1>; return values.length - 1; } public void setData(int dataId, Object dataValue) { values[dataId] = dataValue; } public <T> T getData(int dataId) { return values[dataId]; }
But, what I suggested after is to not allow influencers to set more than 1 data. So, they can only reserve 1 slot and they manage this slot as they like (with the data structure they want). For that, there are many ways to proceed:
- There is no control on which data type they declare. For this, a set containing the influencers that had already reserved their slot sould be created, so for reserving data, you also must specify the THIS influencer (this could be easily bypassed)
-
There is an InfluencerData interface that must be implemented by all those data structures. Those are initialized, however, in the ParticleEmitterNode and passed to the influencer in the influencer's initialize method. To initialize this data there are two possible ways:
- Reflection with the structure class that implements the InfluencerData
- Adding a InfluencerData createData() method to the Influencer interface.
-
repo owner @NemesisMate I think this ticket is done, right?
- Log in to comment
I thought about this, the "raw" manner is a better option if you need to have the best performance :( Are you going to make your own influencers?