2 #include "Thruster.hpp"
3 #include "PropEngine.hpp"
4 #include "PistonEngine.hpp"
5 #include "TurbineEngine.hpp"
8 #include "Launchbar.hpp"
12 #include "Propeller.hpp"
15 #include "ControlMap.hpp"
18 ControlMap::~ControlMap()
21 for(i=0; i<_inputs.size(); i++) {
22 Vector* v = (Vector*)_inputs.get(i);
24 for(j=0; j<v->size(); j++)
25 delete (MapRec*)v->get(j);
29 for(i=0; i<_outputs.size(); i++)
30 delete (OutRec*)_outputs.get(i);
33 int ControlMap::newInput()
35 Vector* v = new Vector();
36 return _inputs.add(v);
39 void ControlMap::addMapping(int input, int type, void* object, int options,
40 float src0, float src1, float dst0, float dst1)
42 addMapping(input, type, object, options);
44 // The one we just added is last in the list (ugly, awful hack!)
45 Vector* maps = (Vector*)_inputs.get(input);
46 MapRec* m = (MapRec*)maps->get(maps->size() - 1);
54 void ControlMap::addMapping(int input, int type, void* object, int options)
56 // See if the output object already exists
59 for(i=0; i<_outputs.size(); i++) {
60 OutRec* o = (OutRec*)_outputs.get(i);
61 if(o->object == object && o->type == type) {
67 // Create one if it doesn't
72 out->oldL = out->oldR = out->time = 0;
76 // Make a new input record
77 MapRec* map = new MapRec();
80 map->idx = out->maps.add(map);
82 // The default ranges differ depending on type!
83 map->src1 = map->dst1 = rangeMax(type);
84 map->src0 = map->dst0 = rangeMin(type);
86 // And add it to the approproate vectors.
87 Vector* maps = (Vector*)_inputs.get(input);
91 void ControlMap::reset()
93 // Set all the values to zero
94 for(int i=0; i<_outputs.size(); i++) {
95 OutRec* o = (OutRec*)_outputs.get(i);
96 for(int j=0; j<o->maps.size(); j++)
97 ((MapRec*)(o->maps.get(j)))->val = 0;
101 void ControlMap::setInput(int input, float val)
103 Vector* maps = (Vector*)_inputs.get(input);
104 for(int i=0; i<maps->size(); i++) {
105 MapRec* m = (MapRec*)maps->get(i);
109 // Do the scaling operation. Clamp to [src0:src1], rescale to
110 // [0:1] within that range, then map to [dst0:dst1].
111 if(val2 < m->src0) val2 = m->src0;
112 if(val2 > m->src1) val2 = m->src1;
113 val2 = (val2 - m->src0) / (m->src1 - m->src0);
114 val2 = m->dst0 + val2 * (m->dst1 - m->dst0);
120 int ControlMap::getOutputHandle(void* obj, int type)
122 for(int i=0; i<_outputs.size(); i++) {
123 OutRec* o = (OutRec*)_outputs.get(i);
124 if(o->object == obj && o->type == type)
130 void ControlMap::setTransitionTime(int handle, float time)
132 ((OutRec*)_outputs.get(handle))->time = time;
135 float ControlMap::getOutput(int handle)
137 return ((OutRec*)_outputs.get(handle))->oldL;
140 float ControlMap::getOutputR(int handle)
142 return ((OutRec*)_outputs.get(handle))->oldR;
145 void ControlMap::applyControls(float dt)
148 for(outrec=0; outrec<_outputs.size(); outrec++) {
149 OutRec* o = (OutRec*)_outputs.get(outrec);
151 // Generate a summed value. Note the check for "split"
152 // control axes like ailerons.
153 float lval = 0, rval = 0;
155 for(i=0; i<o->maps.size(); i++) {
156 MapRec* m = (MapRec*)o->maps.get(i);
159 if(m->opt & OPT_SQUARE)
160 val = val * Math::abs(val);
161 if(m->opt & OPT_INVERT)
164 if(m->opt & OPT_SPLIT)
170 // If there is a finite transition time, clamp the values to
171 // the maximum travel allowed in this dt.
173 float dl = lval - o->oldL;
174 float dr = rval - o->oldR;
175 float adl = Math::abs(dl);
176 float adr = Math::abs(dr);
178 float max = (dt/o->time) * (rangeMax(o->type) - rangeMin(o->type));
179 if(adl > max) dl = dl*max/adl;
180 if(adr > max) dr = dr*max/adr;
189 void* obj = o->object;
191 case THROTTLE: ((Thruster*)obj)->setThrottle(lval); break;
192 case MIXTURE: ((Thruster*)obj)->setMixture(lval); break;
193 case CONDLEVER: ((TurbineEngine*)((PropEngine*)
194 obj)->getEngine())->setCondLever(lval); break;
195 case STARTER: ((Thruster*)obj)->setStarter(lval != 0.0); break;
196 case MAGNETOS: ((PropEngine*)obj)->setMagnetos((int)lval); break;
197 case ADVANCE: ((PropEngine*)obj)->setAdvance(lval); break;
198 case PROPPITCH: ((PropEngine*)obj)->setPropPitch(lval); break;
199 case PROPFEATHER: ((PropEngine*)obj)->setPropFeather((int)lval); break;
200 case REHEAT: ((Jet*)obj)->setReheat(lval); break;
201 case VECTOR: ((Jet*)obj)->setRotation(lval); break;
202 case BRAKE: ((Gear*)obj)->setBrake(lval); break;
203 case STEER: ((Gear*)obj)->setRotation(lval); break;
204 case EXTEND: ((Gear*)obj)->setExtension(lval); break;
205 case HEXTEND: ((Hook*)obj)->setExtension(lval); break;
206 case LEXTEND: ((Launchbar*)obj)->setExtension(lval); break;
207 case LACCEL: ((Launchbar*)obj)->setAcceleration(lval); break;
208 case CASTERING:((Gear*)obj)->setCastering(lval != 0); break;
209 case SLAT: ((Wing*)obj)->setSlat(lval); break;
210 case FLAP0: ((Wing*)obj)->setFlap0(lval, rval); break;
211 case FLAP0EFFECTIVENESS: ((Wing*)obj)->setFlap0Effectiveness(lval); break;
212 case FLAP1: ((Wing*)obj)->setFlap1(lval, rval); break;
213 case FLAP1EFFECTIVENESS: ((Wing*)obj)->setFlap1Effectiveness(lval); break;
214 case SPOILER: ((Wing*)obj)->setSpoiler(lval, rval); break;
215 case COLLECTIVE: ((Rotor*)obj)->setCollective(lval); break;
216 case CYCLICAIL: ((Rotor*)obj)->setCyclicail(lval,rval); break;
217 case CYCLICELE: ((Rotor*)obj)->setCyclicele(lval,rval); break;
218 case TILTPITCH: ((Rotor*)obj)->setTiltPitch(lval); break;
219 case TILTYAW: ((Rotor*)obj)->setTiltYaw(lval); break;
220 case TILTROLL: ((Rotor*)obj)->setTiltRoll(lval); break;
222 ((Rotor*)obj)->setRotorBalance(lval); break;
223 case ROTORBRAKE: ((Rotorgear*)obj)->setRotorBrake(lval); break;
225 ((Rotorgear*)obj)->setEngineOn((int)lval); break;
226 case ROTORENGINEMAXRELTORQUE:
227 ((Rotorgear*)obj)->setRotorEngineMaxRelTorque(lval); break;
229 ((Rotorgear*)obj)->setRotorRelTarget(lval); break;
230 case REVERSE_THRUST: ((Jet*)obj)->setReverse(lval != 0); break;
232 ((PistonEngine*)((Thruster*)obj)->getEngine())->setBoost(lval);
235 ((PistonEngine*)((Thruster*)obj)->getEngine())->setWastegate(lval);
237 case WINCHRELSPEED: ((Hitch*)obj)->setWinchRelSpeed(lval); break;
238 case HITCHOPEN: ((Hitch*)obj)->setOpen(lval!=0); break;
239 case PLACEWINCH: ((Hitch*)obj)->setWinchPositionAuto(lval!=0); break;
240 case FINDAITOW: ((Hitch*)obj)->findBestAIObject(lval!=0); break;
245 float ControlMap::rangeMin(int type)
247 // The minimum of the range for each type of control
249 case FLAP0: return -1; // [-1:1]
250 case FLAP1: return -1;
251 case STEER: return -1;
252 case CYCLICELE: return -1;
253 case CYCLICAIL: return -1;
254 case COLLECTIVE: return -1;
255 case WINCHRELSPEED: return -1;
256 case MAGNETOS: return 0; // [0:3]
257 case FLAP0EFFECTIVENESS: return 1; // [0:10]
258 case FLAP1EFFECTIVENESS: return 1; // [0:10]
259 default: return 0; // [0:1]
263 float ControlMap::rangeMax(int type)
265 // The maximum of the range for each type of control
267 case FLAP0: return 1; // [-1:1]
268 case FLAP1: return 1;
269 case STEER: return 1;
270 case MAGNETOS: return 3; // [0:3]
271 case FLAP0EFFECTIVENESS: return 10;// [0:10]
272 case FLAP1EFFECTIVENESS: return 10;// [0:10]
273 default: return 1; // [0:1]