• Advertisement


GDNet+ Standard
  • Content count

  • Joined

  • Last visited

Community Reputation

1439 Excellent

About noizex

  • Rank

Personal Information

  • Interests

Recent Profile Visitors

9989 profile views
  1. I managed to rewrite how metadata is extracted, seems to work but needs more testing. It now returns std::vector<std::string> for metadata instead of just single string and allows storing unlimited number of metadatas per type. I'm right now investigating how *mixin class* behaves, as when I included file with a defined mixin and that mixin has metadata on one of the properties, it seems to break on compilation try. Considering such mixin is included, I'm not really sure this goes through metadata extraction - checking right now when include mechanism kicks in and if it's after or before extraction. @WitchLord how are mixins treated internally? As I assume they may not exist as a type? Right now it seems that extracting part is missing mixin decls from metadata extraction, but after I started thinking about it I'm not sure it's even possible to have metadata for mixin? It would make sense from class that implements mixin as it basically inherits its properties (which can have metadata), but not sure it's possible right now.
  2. Trying it now with most recent source as it seems that something changed in the way declarations are looked up. Will let you know when I have something ready to show.
  3. You replied as I were typing some update So, I spent some time hacking ScriptBuilder and managed to add both functions, so storing multiple metadata per decl (I prefer non-nested syntax so each [] separately rather than braces inside braces, this is pretty trival because it already parses it, just needs different way of storing, as mentioned multimap instead of map) and adding special type of meta_data that allows excluding parts of the code. To make it more universal I think I will add some callback that can decide whether section should be skipped or not. Not sure how bulletproof it is yet, as I know very little about the way it parses, but it overrides methods, variables and global functions from what I checked, so almost all things that I need hidden. I downloaded SVN code and will do some changeset in case someone is interested.
  4. Prevent assigning non-refcounted references

    Thanks for sharing, I'll have a look at the code and use it as a guide. Regarding the issue discussed, I'll go for exposing only methods and not the whole type - similar to how you do, so all the attributes will be on the game object, not accessed through specific classes like Transform, Rigidbody etc. This should simplify the situation and avoid problem with ownership.
  5. Hello, I'm working on a client-server architecture for my game and I'd like to reuse code as much as possible - while it may be possible to split server and client code into separate source files, it would be much easier to follow if I could somehow annotate methods and variables with meta data - which is what ScriptBuilder is already capable of. There are two problems to fully make use of it: 1) ScriptBuilder seems to only allow single [] metainfo - it can't collect all of them and put them into an array. I will look into the way to add this possibility - do you think it would make sense to include in ScriptBuilder, or I should keep it for myself? This change would allow to put metainfo in such way, which will be very useful for me: (UPDATE: This may actually work, for some reason I think I was getting assert when "stacking" meta data, now I'm running it and it seems to gather them all, I'll see if it works till the point of fetching) UPDATE2: It's partially possible - the data is there but it's getting lost when saving to the final meta-data map, because it's a map, so multiple values will get ignored when inserting. I'm checking if changing this storage to std::multimap and slightly changing retrieval methods wouldn't make it possible to have multiple metainfo. [sync] [persistent] [doc="This is current amount of health points"] int health; 2) Second thing is ability to annotate methods and vars as server or client-only. I know there is a possibility to leave some code out by using #ifdefs but this isn't pretty compared to doing it like this: [sever-only] void calculateDamage(Object@ target, Object@ attacker); [client-only] void spawnParticleEffect(); Unfortunately due to deferred way that metadata is gathered I have no idea if it's even possible to leave out certain method or variable during compilation based on what's marked as such in metainfo. But the final result would be including first method only when compiling on server and second only for client execution. Maybe someone has idea how to achieve this in some reasonable way - the fallback solution is just slapping tons of #ifs in each script, but per-method&variable approach would make it much cleaner. Thanks!
  6. Makes sense, I was thinking maybe it's possible to call "method body" part of the constructor, so assuming that memory is initialized and it won't happen twice, just execute whatever script user provided in the ctor. Sometimes it may have some additional initialize stuff that should happen even if the object is deserialized (like kick off some timer maybe?) - if this skips constructor there is a chance it will fill the object with proper values, but something will not be triggered properly. This probably also means there are some edge cases where Serialize addon won't work fully with the object. I can't think of any reasonable case like this, but something in lines with: class Foo { float lifetime; Foo(float lifetime_) { lifetime = lifetime_; setTimeout(lifetime, "doDie"); } void doDie() { deleteMe(); } } My case is slightly different, it's about initializing from templates rather than by using the class directly, but it has a lot in common with serialization/deserialization. One solution that comes to mind that could work for both, my case and serialization, would be to have some designated init() method that's known to work properly for both situations. Then object initialized with constructor would call init() as would object which has been deserialized. And having a rule that constructor should really only initialize the members. Another one, that would allow keeping constructors untouched, would be to have a special "post serialize" callback in the script and allow script to know when it was deserialized to properly "resume" object. Anyway thanks for explanation! I think from the documentation it wasn't clear if there is some way to call just the body of the constructor without it constructing another instance, now I know there isn't. Maybe worth stating that "constructor should not be called" as this will result in a wrong behaviour and there is no way to execute the body of the method itself, so there is no single reason to ever call ctor when using this way of initialization.
  7. Prevent assigning non-refcounted references

    Thanks for the answer, Andreas! I wasn't sure I understand the limitations of asOBJ_NOHANDLE correctly. Unfortunately it would not make much sense to make it value type - as Transform is just one example of such object (and even it has more members: position / orientation / scale), there are more like Mesh, Rigidbody, Animator - always a single instance per game object. The idea was that C++ has low-level, non-logic C++ "components" for complex stuff (animations, physics), that may or may not be present on the object. Their presence depends on the purpose of the object: if it's a static object with no animations it won't have these available and they would be null, but if it's some monster it would have animator, transform, rigidbody and so on. I also thought it would be fancy to expose them as props so you can refer to them as obj.animator or obj.transform - but it's a single instance and its lifetime should not really depend on ref count but be explicitly controlled by the owning object (removing component is possible if it's no longer needed - say, game object reaches an animation after which it just stays inanimate and does not require a full animator component - for example upon death). But if I say "remove it" I want it to be removed, not kept alive because some script writer decided to store reference to that component somewhere in a script, which should not really happen. I could probably disconnect it from world & object, so even if the instance exists it no longer affects the object, but it may cause a lot of "dangling" components if people are not careful and store the reference somewhere for whole object's lifetime - it would defeat the purpose of removing the component if no longer in acive use. If preventing storing reference or nullifying them all once such component is removed is not an option, I think I will go for less direct method of access to the components that should work - instead of exposing whole component type to script side, I will wrap it in functions - instead of obj.transform.position (where transform is Transform@ and position is vec3 member of it) I could have obj.getPosition(), obj.getRotation(), obj.setPosition() and so on. Each such method will be a wrapper: vec3 getPosition(Object* obj) { asIScriptContext *ctx = asGetActiveContext(); Transform* transform = obj->getComponent<Transform>(); if (transform) { return transform->getPosition(); } else { ctx->SetException("Calling getPosition() on an object without Transform!"); } } This won't "scope" these properties nicely in a way that could be achieved with props - obj.transform.position - but I think I can still wrap some of them at least to obj.position where applicable. And maybe even, instead of throwing script exception where no component is found, add it automatically when it's not found, assuming that calling some method using this component means that the user actually needs it. It also has a positive side, which is not needing to register types for all these components, just wrapper methods for their public interface. I was hoping that there may be some tricky way to achieve what I wanted initially, but if there is no such way right now it's not deal breaker.
  8. Hi, I have a C++ class that may be retrieved inside script object, but I'd like to make it only allow usage when retrieved by method that returns it, and do not allow storing this reference in some variable. Example: # Here I have script property that proxies the retrieval to C++ side object obj Transform@ transform { get { return obj.getTransform() } } # I want these scenarios to be: # allowed obj.transform.position += vec3(1,2,3); someMethod(obj.transform) # disallowed Transform@ t; @t = obj.transform; I tried using opAssign, some asOBJ_NOHANDLE but seems like these won't do what I need? Is it even possible? Thing is that I can ensure Transform@ comes valid from C++ side when it's retrieved through getTransform(), but if it gets stored for longer it may crash the application - there is slim chance for this but it's not guaranteed to exist for a whole lifetime of script object. I could make it refcounted, but making it for a purpose of sharing it inside script, where I don't actually want this to be stored anywhere, doesn't seem to make sense. Does anything in AS exists that would allow me prevent such behaviour? Thanks, noizex
  9. I have specific need to initialize a script object but postpone calling constructor before I do some additional work. I want to do this because constructor may call some methods and use variables that may not be yet initialized, because they're set from outside the script. What will be set depends on some meta info etc. so I basically want to do some work and then call the usual constructor. I found that CreateUninitializedScriptObject does exactly what I need and looks like it works well, but I don't know how should I then call the constructor so it only executes what's in constructor's body and not create a new object? The factory function I retrieved would create new object when called right? Also how does that work with inheritance? If I'm using CreateUninitializedScriptObject on a Foo object and inheritance hierarchy is Foo < Bar < Baz, how can I make sure all constructors are called? Is it even possible when creating uninitialized object? In Serializable addon it's only used to restore object and it says there that calling constructor may have some side-effects, but it does not explicitly say it would create second object instance. So is it possible to call and how it behaves then? And if so - how do I retrieve the type for calling it, as I assume it would be different than factory func?
  10. Why the sudden boom in marching cubes? [Possible target]

    I'd say that boom for Marching Cubes was somewhere around the time Minecraft was released.. PS. I just read initial post fully and you actually mention this haha. Sorry, I just looked at the topic and thought I'd drop some clever remark.. I think it never really ceased, just sometimes comes in waves where people create more "infinite, procedural & voxel terrains". Surface extraction from such volume data was always interesting topic, and the way it innovated working with terrain and finally having real 3D surface instead of faked heightmaps with some artificial holes and added geometry for caves / overhangs. I'm surprised this is not a hot topic for next-gen and everyone sticks to heightmaps still. I think Cryengine had voxel editor for terrian but I'm not sure which games used it. Such terrain provides much more interesting features, but has a lot of problem areas - generating LODs, texturing so I can see why this may not be considered as competition, which is much much easier to deal with. I personally stick to Surface Nets, which are more like wrapping a cloth around some more rough surface, but generates good enough terrain features and works on a binary data volume instead of density field.
  11. Marching Cubes and Dual Contouring Tutorial

    Just quickly skimmed through the articles (will read them fully later), but they look really good visually, these topics are sometimes hard to understand conceptually without a proper visualisations and what I see in these tutorials there is quite impressive Good job and thanks for sharing!
  12. I think the same issue was discussed here recently, see my post and Andreas' answer: For me it doesn't even compile, it looks like it expects some type after private so it definitely parses it as method definition. But I'm quite behind in AS versions so maybe now it parses but has no effect?
  13. I have now working solution where C++ instance is shared between spawnObject method and getCPPObject method through context user data. Seems to work fine, if I instantiate the object it throws exception that it should be instantiated through spawnObject. The last problem I have is with my concept of "one object, one file" - once I set hierarchy of objects deeper than 1, say: object.as: abstract shared Object bar.as: Bar < Object foo.as: Foo < Bar < Object baz.as: Baz < Bar < Object Now when I try to spawn baz.as which has: #include "bar.as" my routine to look for the class name to instantiate fails, as it was naive "first thing that has a base of class Object". It seems that for Baz base class will be Bar so I'd have to recurently check until I reach Object. Is there some way to retrieve the most bottom class in the hierarchy? Or any other method to figure out which type from given script should be instantiated (usually first one that's descendant of Object, but other types will be pulled by include). PS. Found method DerivesFrom(type) which can be called in all encountered types, and it seems that GetObjectTypeCount() starts with bottom classes first, so it goes in an order that works fine for now. Other idea I'm considering is just enforcing naming so "some_item.as" has to define SomeItem class inside and that one will be instantiated when I do spawnObject("some_item.as") -> pros of this is that there will be no "magic guessing"
  14. I tried that but putting private keyword in front of a constructor causes syntax error - I think it's not expecting that keyword together with constructor, so when it sees private, next thing it expects is some return type not method name. class Foo { private Foo() { } } Expected identifier Instead found '(' Unexpected token '~' Unexpected token 'private' Unexpected token '}' Unless I do something wrong, or my AS version is old (I haven't updated it in a while, will try to do it next as it's worth doing an update anyway).
  15. Hmm... I'm trying this but have no idea how to not do too "entangled". Calling function in constructor of script object that throws exception sounds okayish (though I'd gladly not use exception for this and just early or plain prevent instantiation of such objects in scripts without special factory func) but passing spawned object pointer through some connection made through this call seems slightly complicated. It looks like what we'd need is to make a class constructor private or in some other way impossible to instantiate from within script without being created through factory method on C++ side. Any ideas with pseudo code welcome Ideally it would be compile-time - so if it sees instantiation of class that should not be instantiated directly, it just fails to compile, but this would require some language feature UPDATE: Okay I think context could be used to pass that instance between spawning method and obtaining the pointer in ctor, right? User data for that single context should be the same... Trying that now.
  • Advertisement