2 #include "Thruster.hpp"
3 #include "PropEngine.hpp"
4 #include "PistonEngine.hpp"
8 #include "Propeller.hpp"
10 #include "ControlMap.hpp"
13 ControlMap::~ControlMap()
16 for(i=0; i<_inputs.size(); i++) {
17 Vector* v = (Vector*)_inputs.get(i);
19 for(j=0; j<v->size(); j++)
20 delete (MapRec*)v->get(j);
24 for(i=0; i<_outputs.size(); i++)
25 delete (OutRec*)_outputs.get(i);
28 int ControlMap::newInput()
30 Vector* v = new Vector();
31 return _inputs.add(v);
34 void ControlMap::addMapping(int input, int type, void* object, int options,
35 float src0, float src1, float dst0, float dst1)
37 addMapping(input, type, object, options);
39 // The one we just added is last in the list (ugly, awful hack!)
40 Vector* maps = (Vector*)_inputs.get(input);
41 MapRec* m = (MapRec*)maps->get(maps->size() - 1);
49 void ControlMap::addMapping(int input, int type, void* object, int options)
51 // See if the output object already exists
54 for(i=0; i<_outputs.size(); i++) {
55 OutRec* o = (OutRec*)_outputs.get(i);
56 if(o->object == object && o->type == type) {
62 // Create one if it doesn't
67 out->oldL = out->oldR = out->time = 0;
71 // Make a new input record
72 MapRec* map = new MapRec();
75 map->idx = out->maps.add(map);
77 // The default ranges differ depending on type!
78 map->src1 = map->dst1 = rangeMax(type);
79 map->src0 = map->dst0 = rangeMin(type);
81 // And add it to the approproate vectors.
82 Vector* maps = (Vector*)_inputs.get(input);
86 void ControlMap::reset()
88 // Set all the values to zero
89 for(int i=0; i<_outputs.size(); i++) {
90 OutRec* o = (OutRec*)_outputs.get(i);
91 for(int j=0; j<o->maps.size(); j++)
92 ((MapRec*)(o->maps.get(j)))->val = 0;
96 void ControlMap::setInput(int input, float val)
98 Vector* maps = (Vector*)_inputs.get(input);
99 for(int i=0; i<maps->size(); i++) {
100 MapRec* m = (MapRec*)maps->get(i);
104 // Do the scaling operation. Clamp to [src0:src1], rescale to
105 // [0:1] within that range, then map to [dst0:dst1].
106 if(val2 < m->src0) val2 = m->src0;
107 if(val2 > m->src1) val2 = m->src1;
108 val2 = (val2 - m->src0) / (m->src1 - m->src0);
109 val2 = m->dst0 + val2 * (m->dst1 - m->dst0);
115 int ControlMap::getOutputHandle(void* obj, int type)
117 for(int i=0; i<_outputs.size(); i++) {
118 OutRec* o = (OutRec*)_outputs.get(i);
119 if(o->object == obj && o->type == type)
125 void ControlMap::setTransitionTime(int handle, float time)
127 ((OutRec*)_outputs.get(handle))->time = time;
130 float ControlMap::getOutput(int handle)
132 return ((OutRec*)_outputs.get(handle))->oldL;
135 float ControlMap::getOutputR(int handle)
137 return ((OutRec*)_outputs.get(handle))->oldR;
140 void ControlMap::applyControls(float dt)
143 for(outrec=0; outrec<_outputs.size(); outrec++) {
144 OutRec* o = (OutRec*)_outputs.get(outrec);
146 // Generate a summed value. Note the check for "split"
147 // control axes like ailerons.
148 float lval = 0, rval = 0;
150 for(i=0; i<o->maps.size(); i++) {
151 MapRec* m = (MapRec*)o->maps.get(i);
154 if(m->opt & OPT_SQUARE)
155 val = val * Math::abs(val);
156 if(m->opt & OPT_INVERT)
159 if(m->opt & OPT_SPLIT)
165 // If there is a finite transition time, clamp the values to
166 // the maximum travel allowed in this dt.
168 float dl = lval - o->oldL;
169 float dr = rval - o->oldR;
170 float adl = Math::abs(dl);
171 float adr = Math::abs(dr);
173 float max = (dt/o->time) * (rangeMax(o->type) - rangeMin(o->type));
174 if(adl > max) dl = dl*max/adl;
175 if(adr > max) dr = dr*max/adr;
184 void* obj = o->object;
186 case THROTTLE: ((Thruster*)obj)->setThrottle(lval); break;
187 case MIXTURE: ((Thruster*)obj)->setMixture(lval); break;
188 case STARTER: ((Thruster*)obj)->setStarter(lval != 0.0); break;
189 case MAGNETOS: ((PropEngine*)obj)->setMagnetos((int)lval); break;
190 case ADVANCE: ((PropEngine*)obj)->setAdvance(lval); break;
191 case PROPPITCH: ((PropEngine*)obj)->setPropPitch(lval); break;
192 case REHEAT: ((Jet*)obj)->setReheat(lval); break;
193 case VECTOR: ((Jet*)obj)->setRotation(lval); break;
194 case BRAKE: ((Gear*)obj)->setBrake(lval); break;
195 case STEER: ((Gear*)obj)->setRotation(lval); break;
196 case EXTEND: ((Gear*)obj)->setExtension(lval); break;
197 case CASTERING:((Gear*)obj)->setCastering(lval != 0); break;
198 case SLAT: ((Wing*)obj)->setSlat(lval); break;
199 case FLAP0: ((Wing*)obj)->setFlap0(lval, rval); break;
200 case FLAP1: ((Wing*)obj)->setFlap1(lval, rval); break;
201 case SPOILER: ((Wing*)obj)->setSpoiler(lval, rval); break;
203 ((Thruster*)obj)->getPistonEngine()->setBoost(lval);
209 float ControlMap::rangeMin(int type)
211 // The minimum of the range for each type of control
213 case FLAP0: return -1; // [-1:1]
214 case FLAP1: return -1;
215 case STEER: return -1;
216 case MAGNETOS: return 0; // [0:3]
217 default: return 0; // [0:1]
221 float ControlMap::rangeMax(int type)
223 // The maximum of the range for each type of control
225 case FLAP0: return 1; // [-1:1]
226 case FLAP1: return 1;
227 case STEER: return 1;
228 case MAGNETOS: return 3; // [0:3]
229 default: return 1; // [0:1]