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. |
---|
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 | { |
---|
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; |
---|
56 | } |
---|
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; } |
---|
68 | }; |
---|
69 | |
---|
70 | template<class ID, class T, int N> char UserTags<ID,T,N>::reg[N]={0}; |
---|
71 | |
---|
72 | #endif |
---|