[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 | |
---|
[793] | 43 | template<class ID, class T, int N> class UserTags |
---|
[109] | 44 | { |
---|
[793] | 45 | static char reg[N]; |
---|
| 46 | T data[N]; |
---|
| 47 | public: |
---|
| 48 | UserTags() { memset(data, 0, sizeof(data)); } |
---|
[109] | 49 | |
---|
[793] | 50 | /** allocate new id */ |
---|
| 51 | static int newID() |
---|
[109] | 52 | { |
---|
[793] | 53 | for (int i = 1; i < N; i++) if (!reg[i]) { reg[i] = 1; return i; } |
---|
| 54 | DB(printf("Warning: UserTags run out of ids!\n")); |
---|
| 55 | return 0; |
---|
[109] | 56 | } |
---|
[793] | 57 | static void freeID(int id) |
---|
| 58 | { |
---|
| 59 | reg[id] = 0; |
---|
| 60 | } |
---|
| 61 | T& operator[](int id) |
---|
| 62 | { |
---|
| 63 | DB(if (!id) printf("Warning: UserTags @ %p is using id=0\n", this);) |
---|
| 64 | return data[id]; |
---|
| 65 | } |
---|
| 66 | operator T() { return data[0]; } |
---|
| 67 | void operator=(T x) { data[0] = x; } |
---|
[109] | 68 | }; |
---|
| 69 | |
---|
[844] | 70 | template<class ID, class T, int N> char UserTags<ID,T,N>::reg[N]={0}; |
---|
| 71 | |
---|
[109] | 72 | #endif |
---|