A discussion of customized prop discs for authors can be found here.
- Download as a project for Xcode 14 or newer (64-bit Intel)
- Download as a project for Microsoft Visual Studio 2017 (64-bit; requires Windows 8.1 SDK)
- Download as a project for GCC 4.x/Linux (64-bit)
#include <string.h>
#include <math.h>
#include "XPLMDataAccess.h"
#include "XPLMProcessing.h"
static XPLMDataRef prop_rotation_speed_rad_sec = NULL;
static XPLMDataRef prop_rotation_angle_deg = NULL;
static XPLMDataRef side_angle = NULL;
static XPLMDataRef prop_is_disc = NULL;
static XPLMDataRef disc_s = NULL;
static XPLMDataRef disc_t = NULL;
static XPLMDataRef side_s = NULL;
static XPLMDataRef side_t = NULL;
static XPLMDataRef sim_speed = NULL;
static XPLMDataRef frame_rate_period = NULL;
// Interp - rescales a floating point variable, clamping to the outer limits. Handy
// for mapping a range of physics behavior to something in the graphics.
static float interp(float in1, float out1, float in2, float out2, float x)
{
if(x < in1) return out1;
if(x > in2) return out2;
return out1 + (out2 - out1) * (x - in1) / (in2 - in1);
}
// Two util funcs to write the first two slots of array datarefs...we do this a lot,
// so this saves some typing.
static void set_2f(XPLMDataRef r, float v1, float v2)
{
float v[2] = { v1, v2 };
XPLMSetDatavf(r,v,0,2);
}
static void set_2i(XPLMDataRef r, int i1, int i2)
{
int i[2] = { i1, i2 };
XPLMSetDatavi(r,i,0,2);
}
static float deferred_init(
float inElapsedSinceLastCall,
float inElapsedTimeSinceLastFlightLoop,
int inCounter,
void * inRefcon)
{
// These get set once when we take over the airplane...these are custom prop disc settings that
// we won't change per frame.
set_2i(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/override"), 1, 1);
// Our prop disc has 4 slots across and 2 down.
set_2i(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/disc_s_dim"), 4, 4);
set_2i(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/disc_t_dim"), 2, 2);
// Alpha settings for the prop disc.
set_2f(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/disc_alpha_front"), 1.0, 1.0);
set_2f(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/disc_alpha_side"), 0.1, 0.1);
set_2f(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/disc_alpha_inside"), 0.8, 0.8);
// Side is a 2-blade prop 15 cm wide. We have 32x2 slots for side discs.
set_2f(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_width") , 0.15, 0.15);
set_2i(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_number_of_blades"), 2, 2);
set_2i(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_s_dim"), 32, 32);
set_2i(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_t_dim"), 2, 2);
// Alpha setting for side disc is separate
set_2f(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_alpha_front"), 0.0, 0.0);
set_2f(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_alpha_side"), 1.0, 1.0);
set_2f(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_alpha_inside"), 0.8, 0.8);
// Do not use auto-billboarding. We will spin the side disc ourselves.
set_2i(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_is_billboard"), 0, 0);
return 0;
}
static float prop_per_frame(
float inElapsedSinceLastCall,
float inElapsedTimeSinceLastFlightLoop,
int inCounter,
void * inRefcon)
{
float prop_speed_now[2];
float prop_angle_now[2];
float side_angle_now[2];
// First we need to know how fast the sim is really running - a function
// of the sim speed and framerate period. We also need to know how fast our
// disc is going. Btw s in seconds per frame.
float s = XPLMGetDatai(sim_speed);
s *= XPLMGetDataf(frame_rate_period);
XPLMGetDatavf(prop_rotation_speed_rad_sec,prop_speed_now,0,2);
// And - where is our disc right now.
XPLMGetDatavf(side_angle,side_angle_now,0,2);
XPLMGetDatavf(prop_rotation_angle_deg,prop_angle_now,0,2);
// "Spin" the disc just a bit and write it bck.
prop_angle_now[0] += prop_speed_now[0] * s * 60.0;
prop_angle_now[1] += prop_speed_now[1] * s * 60.0;
side_angle_now[0] += prop_speed_now[0] * s * 60.0;
side_angle_now[1] += prop_speed_now[1] * s * 60.0;
XPLMSetDatavf(side_angle,side_angle_now, 0, 2);
XPLMSetDatavf(prop_rotation_angle_deg,prop_angle_now, 0, 2);
// Individual blades or a disc? We switch at greater than 18 rads/sec spinning.
set_2i(prop_is_disc, prop_speed_now[0] > 18.0, prop_speed_now[1] > 18.0);
// We pick our texture slots by interping the prop speed. So as the prop speeds up, we
// pick different slots.
set_2f(disc_s,interp(15,0,100,2,prop_speed_now[0]),interp(15,0,100,2,prop_speed_now[1]));
set_2i(disc_t,0,1);
set_2f(side_s,interp(15,26,100,24,prop_speed_now[0]),interp(15,24,100,26,prop_speed_now[1]));
set_2i(side_t,0,1);
return -1.0;
}
PLUGIN_API int XPluginStart(
char * outName,
char * outSig,
char * outDesc)
{
strcpy(outName, "Custom Prop Disc Example");
strcpy(outSig, "xplanesdk.examples.custom_prop_disc");
strcpy(outDesc, "A plugin that demonstrates custom prop disc patterns.");
XPLMRegisterFlightLoopCallback(deferred_init, -1.0, NULL);
XPLMRegisterFlightLoopCallback(prop_per_frame, -2.0, NULL);
prop_rotation_speed_rad_sec = XPLMFindDataRef("sim/flightmodel2/engines/prop_rotation_speed_rad_sec");
prop_rotation_angle_deg = XPLMFindDataRef("sim/flightmodel2/engines/prop_rotation_angle_deg");
side_angle = XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_angle");
prop_is_disc = XPLMFindDataRef("sim/flightmodel2/engines/prop_is_disc");
disc_s = XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/disc_s");
disc_t = XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/disc_t");
side_s = XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_s");
side_t = XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/side_t");
sim_speed = XPLMFindDataRef("sim/time/sim_speed");
frame_rate_period = XPLMFindDataRef("sim/operation/misc/frame_rate_period");
return 1;
}
PLUGIN_API void XPluginStop(void)
{
XPLMUnregisterFlightLoopCallback(deferred_init,NULL);
XPLMUnregisterFlightLoopCallback(prop_per_frame,NULL);
set_2i(XPLMFindDataRef("sim/flightmodel2/engines/prop_disc/override"), 0, 0);
}
PLUGIN_API void XPluginDisable(void)
{
}
PLUGIN_API int XPluginEnable(void)
{
return 1;
}
PLUGIN_API void XPluginReceiveMessage(
XPLMPluginID inFromWho,
int inMessage,
void * inParam)
{
}