[286] | 1 | // This file is a part of Framsticks SDK. http://www.framsticks.com/ |
---|
| 2 | // Copyright (C) 1999-2015 Maciej Komosinski and Szymon Ulatowski. |
---|
| 3 | // See LICENSE.txt for details. |
---|
[109] | 4 | |
---|
| 5 | #ifndef _USERTAGS_H_ |
---|
| 6 | #define _USERTAGS_H_ |
---|
| 7 | |
---|
| 8 | /** |
---|
| 9 | UserTags is the fast way to associate custom data with general purpose objects. |
---|
| 10 | Objects don't have to know about their users and we can add more users later without recompilation. |
---|
| 11 | For example: MechObject is general physical object in MechaStick engine. |
---|
| 12 | In Framsticks simulator every MechObject is connected with Model object, MechParts and MechJoints are |
---|
| 13 | connected with their counterparts in the Model as well, but the MechObject doesn't even know about it. |
---|
| 14 | If the SSG visualisation is used, the same MechObject is also connected with SSGFramObject. |
---|
| 15 | UserTags class is implemented as array, therefore the access is very fast but we have to define |
---|
| 16 | maximum possible number of tags for every object: |
---|
| 17 | |
---|
| 18 | UserTags<anyclass,datatype,maximumtags> object; |
---|
| 19 | (all UserTags object for a given 'anyclass' will share registered id's) |
---|
| 20 | |
---|
| 21 | usage: |
---|
| 22 | 1.allocate private id: |
---|
| 23 | int id=object->userdata.newID(); |
---|
| 24 | 'id' is shared across all objects of that class (in this example) |
---|
| 25 | and therefore you need to allocate it only once. |
---|
| 26 | 0 is illegal here and means that we run out of id values. |
---|
| 27 | |
---|
| 28 | 2.now you can use id to access your private data inside UserTags: |
---|
| 29 | object->userdata[id]=...; |
---|
| 30 | ...=object->userdata[id]; |
---|
| 31 | ... |
---|
| 32 | 3.you can also assign/access object->userdata (which is a shortcut for |
---|
| 33 | object->userdata[0]). no id here, so in that case it is your responsibility |
---|
| 34 | to avoid conflicts. |
---|
| 35 | object->userdata=...; |
---|
| 36 | ...=object->userdata; |
---|
| 37 | ... |
---|
| 38 | |
---|
| 39 | 4.free your id when finished: |
---|
| 40 | object->userdata.freeID(id); |
---|
| 41 | */ |
---|
| 42 | |
---|
| 43 | template<class ID,class T,int N> class UserTags |
---|
| 44 | { |
---|
| 45 | static char reg[N]; |
---|
| 46 | T data[N]; |
---|
| 47 | public: |
---|
| 48 | UserTags() {memset(data,0,sizeof(data));} |
---|
| 49 | |
---|
| 50 | /** allocate new id */ |
---|
| 51 | static int newID() |
---|
| 52 | { for(int i=1;i<N;i++) if (!reg[i]) {reg[i]=1; return i;} |
---|
| 53 | DB(printf("Warning: UserTags run out of ids!\n")); |
---|
| 54 | return 0; } |
---|
| 55 | static void freeID(int id) |
---|
| 56 | { reg[id]=0; } |
---|
| 57 | T& operator[](int id) |
---|
| 58 | { |
---|
| 59 | DB(if (!id) printf("Warning: UserTags @ %p is using id=0\n",this);) |
---|
| 60 | return data[id]; |
---|
| 61 | } |
---|
| 62 | operator T() { return data[0]; } |
---|
| 63 | void operator=(T x) { data[0]=x; } |
---|
| 64 | }; |
---|
| 65 | |
---|
| 66 | #endif |
---|
| 67 | |
---|
| 68 | |
---|
| 69 | |
---|
| 70 | |
---|
| 71 | |
---|