Jump to content
  • Advertisement


GDNet+ Standard
  • Content count

  • Joined

  • Last visited

Community Reputation

1439 Excellent

About noizex

  • Rank

Personal Information

  • Role
    Creative Director
  • Interests

Recent Profile Visitors

10204 profile views
  1. Ok, I also found some small bugs like not taking into account keywords like shared and abstract when extracting metadata, so this skipped such classes and never found the metadata for them. I'm not sure if the "stacked" metadata functionality will be of any use to anyone and if it's worth adding to the default builder - I definitely need a lot of metadata for my client/server annotations (synchronizing state, persisting - I want it all defined in a most convenient and readable way, which happens to be metadata) so I will keep these changes locally. I attach a changeset it if you want to have a look into my solution - I'm not really experienced in parsing, so this may be a bit hacky, but I tried to make it robust and as generic as possible. It won't be backwards compatible because it makes no sense to keep the const char* methods for accessing metadata (although they can remain as wrappers to new methods, which just call the new ones and extract first element of the vector, this would allow to keep this backwards compat) when I added a generic solution that works for 0..n metadata strings. I also tried to avoid C++11+ features, just in case you'd like to use some of this code. Makes these loops pretty ugly and verbose, could be cleaned a bit with some typedefs though. Btw, it's been AGES since I used SVN, I'm so used to GIT workflow now I actually didn't even realize that comitting to SVN repo pushes this to remote As I have no idea how to collaborate using this VCS, I'm just attaching changeset - mind that it's not final and still trying to make it better and finding some edge cases where metadata is not properly recognized. Would love to hear what you think. Maybe it would make more sense to use different container than multimap, but I went for the quickest solution which didn't involve bigger refactoring of how metadata is inserted into these maps. PS. Sorry for some messed up indentation in patch, I use spaces and it seems AS uses tabs, I did re-convert back to tabs but seems like some indents are now wrong after that. metadata_changes_v1.patch
  2. Thanks - I will try, though it may be just easier to accept mixins can't have metadata I will see if this will lead anywhere. One question because it's not clear to me - metadata will be saved for a class it's been defined in, so if I have Foo < Bar and I have property with metaclass in Bar it won't show up when I iterate properties of Foo, even if the property itself is listed? So to gether all metadatas, I'll need to go down the inheritance tree and check all properties on each following type, right?
  3. 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.
  4. 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.
  5. 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.
  6. noizex

    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.
  7. 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!
  8. 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.
  9. noizex

    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.
  10. 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
  11. 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?
  12. noizex

    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.
  13. noizex

    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!
  14. 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?
  15. 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"
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!