AntTweakBar

 view release on metacpan or  search on metacpan

lib/AntTweakBar.xs  view on Meta::CPAN

  if(!result)
    Perl_croak(aTHX_ "Refreshing error: %s", TwGetLastError());
}

void _set_bar_parameter(TwBar* bar, const char* param_name, const char* param_value) {
  dTHX;
  int result = TwSetParam(bar, NULL, param_name, TW_PARAM_CSTRING, 1, param_value);
  if(!result)
    Perl_croak(aTHX_ "Error applying value '%s' to parameter %s : %s",
	       param_value, param_name, TwGetLastError());
}

void _set_variable_parameter(TwBar* bar, const char* variable, 
			     const char* param_name, const char* param_value) {
  dTHX;
  int result = TwSetParam(bar, variable, param_name, TW_PARAM_CSTRING, 1, param_value);
  if(!result)
    Perl_croak(aTHX_ "Error applying value '%s' of parameter %s to variable %s : %s",
	       param_value, param_name, variable, TwGetLastError());
}

/* CALLBACKS */
/* int/bool callbacks */

void TW_CALL _int_getter(void* value, void* data){
  dTHX;
  SV* sv = SvRV((SV*) data);
  SvGETMAGIC(sv);
  int iv = SvOK(sv) ? SvIV(sv) : 0;
  *(int*)value = iv;
}

void TW_CALL _int_getter_cb(void* value, void* data){
  dTHX;
  SV** cb = hv_fetch(_cb_read_map, (char*) data, sizeof(SV*), 0);
  dSP;
  PUSHMARK(SP);
  int count = call_sv(*cb, G_NOARGS|G_SCALAR);
  SPAGAIN;
  if (count != 1)
    Perl_croak(aTHX_ "Expected 1 arg to be returned from _int_getter \n");
  SV* sv = POPs;
  *(int*)value = SvOK(sv) ? SvIV(sv) : 0;
}

void TW_CALL _int_setter(const void* value, void* data){
  dTHX;
  SV* sv = SvRV((SV*) data);
  sv_setiv(sv, *(int*)value );
  SvSETMAGIC(sv);
}

void TW_CALL _int_setter_cb(const void* value, void* data){
  dTHX;
  SV** cb = hv_fetch(_cb_write_map, (char*) data, sizeof(SV*), 0);
  dSP;
  ENTER;
  SAVETMPS;
  PUSHMARK(SP);
  XPUSHs(sv_2mortal(newSViv(*(int*)value)));
  PUTBACK;
    call_sv(*cb, G_DISCARD);
  FREETMPS;
  LEAVE;
}

/* number(double) callbacks */

void TW_CALL _number_getter(void* value, void* data){
  dTHX;
  SV* sv = SvRV((SV*) data);
  SvGETMAGIC(sv);
  double dv = SvOK(sv) ? SvNV(sv) : 0.0;
  *(double*)value = dv;
}

void TW_CALL _number_setter(const void* value, void* data){
  dTHX;
  SV* sv = SvRV((SV*) data);
  sv_setnv(sv, *(double*)value );
  SvSETMAGIC(sv);
}

void TW_CALL _number_getter_cb(void* value, void* data){
  dTHX;
  SV** cb = hv_fetch(_cb_read_map, (char*) data, sizeof(SV*), 0);
  dSP;
  PUSHMARK(SP);
  int count = call_sv(*cb, G_NOARGS|G_SCALAR);
  SPAGAIN;
  if (count != 1)
    Perl_croak(aTHX_ "Expected 1 arg to be returned from _number_getter_cb \n");
  SV* sv = POPs;
  *(double*)value = SvOK(sv) ? SvNV(sv) : 0.0;
}

void TW_CALL _number_setter_cb(const void* value, void* data){
  dTHX;
  SV** cb = hv_fetch(_cb_write_map, (char*) data, sizeof(SV*), 0);
  dSP;
  ENTER;
  SAVETMPS;
  PUSHMARK(SP);
  XPUSHs(sv_2mortal(newSVnv(*(double*)value)));
  PUTBACK;
    call_sv(*cb, G_DISCARD);
  FREETMPS;
  LEAVE;
}

/* string callbacks */

void TW_CALL _string_getter(void* value, void* data){
  dTHX;
  SV* sv = SvRV((SV*) data);
  SvGETMAGIC(sv);
  const char* string = SvOK(sv) ? SvPV_nolen(sv) : "";
  *(const char**)value = string;
}

void TW_CALL _string_getter_cb(void* value, void* data){
  dTHX;
  SV** cb = hv_fetch(_cb_read_map, (char*) data, sizeof(SV*), 0);
  dSP;
  PUSHMARK(SP);
  int count = call_sv(*cb, G_NOARGS|G_SCALAR);
  SPAGAIN;
  if (count != 1)
    Perl_croak(aTHX_ "Expected 1 arg to be returned from _string_getter_cb \n");
  SV* sv_string = POPs;
  if(!SvPOK(sv_string)) {
    Perl_croak(aTHX_ "_string_getter_cb got not a string\n");
  }
  *(const char**)value = SvPV_nolen(sv_string);
}

void TW_CALL _string_setter(const void* value, void* data){
  dTHX;
  SV* sv = SvRV((SV*) data);
  const char* string = *(const char**)value;
  printf("set string: %s\n", string);
  sv_force_normal(sv);
  sv_setpv(sv, string);
  SvSETMAGIC(sv);
}

void TW_CALL _string_setter_cb(const void* value, void* data){
  dTHX;
  SV** cb = hv_fetch(_cb_write_map, (char*) data, sizeof(SV*), 0);
  dSP;
  ENTER;
  SAVETMPS;
  PUSHMARK(SP);
  XPUSHs(sv_2mortal(newSVpv(*(char**)value, 0)));
  PUTBACK;
    call_sv(*cb, G_DISCARD);
  FREETMPS;
  LEAVE;
}

/* double/float array callback generators */

#define DOUBLE_CALLBACK_GETTER(NAME, NUMBER, TYPE)	 \
void TW_CALL NAME(void* value, void* data) { \
  dTHX; \
  SV* sv = SvRV((SV*) data); \
  if(!(SvTYPE(SvRV(sv)) == SVt_PVAV)){ \
    croak("reference does not point to array any more\n"); \
  } \
  SvGETMAGIC(sv); \
  AV* av = (AV*)SvRV(sv); \
  int my_last = (NUMBER-1); \
  TYPE* values = (TYPE*) value; \
  int i; \
  for(i = 0; i <= my_last; i++) { \
    SV** element = av_fetch(av, i, 0); \
    if(element && SvNOK(*element)) { \
      SvGETMAGIC(*element); \
      values[i] = (TYPE)SvNV(*element); \
    } \
  } \
};

#define DOUBLE_CALLBACK_GETTER_CB(NAME, NUMBER, TYPE) \
void TW_CALL NAME(void* value, void* data) { \
  dTHX;\
  SV** cb = hv_fetch(_cb_read_map, (char*) data, sizeof(SV*), 0); \
  dSP; \
  PUSHMARK(SP); \
  int count = call_sv(*cb, G_NOARGS|G_SCALAR); \
  SPAGAIN; \
  if (count != 1) {\
	char buf[256] = {0}; \
	sprintf(buf, "Expected 1 arg to be returned from %s \n", #NAME); \
	croak(buf); \
  } \
  SV* sv = POPs; \
  if(!(SvTYPE(SvRV(sv)) == SVt_PVAV)){ \
    croak("reference does not point to array any more\n"); \
  } \
  SvGETMAGIC(sv); \
  AV* av = (AV*)SvRV(sv); \
  int my_last = (NUMBER-1);						\
  TYPE* values = (TYPE*) value; \
  int i; \
  for(i = 0; i <= my_last; i++) { \
    SV** element = av_fetch(av, i, 0); \
    if(element && SvNOK(*element)) { \
      SvGETMAGIC(*element); \
      values[i] = (TYPE)SvNV(*element); \
    } \
  } \
};

#define DOUBLE_CALLBACK_SETTER(NAME, NUMBER, TYPE)	 \
void TW_CALL NAME(const void* value, void* data) { \
  dTHX;\
  SV* sv = SvRV((SV*) data); \
  if(!(SvTYPE(SvRV(sv)) == SVt_PVAV)){ \
    croak("reference does not point to array any more\n"); \
  } \
  SvGETMAGIC(sv); \
  AV* av = (AV*)SvRV(sv); \
  int my_last = (NUMBER-1); \
  TYPE* values = (TYPE*) value; \
  int i; \
  for(i = 0; i <= my_last; i++) { \
    SV** element = av_fetch(av, i, 0); \
    if(element) { \
      double value = values[i]; \
      sv_setnv(*element, value); \
      SvGETMAGIC(*element); \
      SvSETMAGIC(sv); \
    } \
  } \
};

#define DOUBLE_CALLBACK_SETTER_CB(NAME, NUMBER, TYPE)	 \
void TW_CALL NAME(const void* value, void* data) { \
  dTHX;\
  SV** cb = hv_fetch(_cb_write_map, (char*) data, sizeof(SV*), 0); \
  dSP; \
  ENTER; \
  SAVETMPS; \
  \
  AV* av = (AV*)sv_2mortal((SV*)newAV()); \
  TYPE* values = (TYPE*) value; \
  int i; \
  for(i = 0; i < NUMBER; i++) { \
    av_push(av, newSVnv(values[i])); \
  } \
  \
  PUSHMARK(SP); \
  XPUSHs(sv_2mortal(newRV_inc((SV*)av))); \
  PUTBACK; \
  \
  call_sv(*cb, G_DISCARD); \
  \
  FREETMPS; \
  LEAVE; \
};


DOUBLE_CALLBACK_GETTER   (_color3f_getter,    3, float);
DOUBLE_CALLBACK_GETTER_CB(_color3f_getter_cb, 3, float);
DOUBLE_CALLBACK_SETTER   (_color3f_setter,    3, float);
DOUBLE_CALLBACK_SETTER_CB(_color3f_setter_cb, 3, float);
DOUBLE_CALLBACK_GETTER   (_color4f_getter,    4, float);
DOUBLE_CALLBACK_GETTER_CB(_color4f_getter_cb, 4, float);
DOUBLE_CALLBACK_SETTER   (_color4f_setter,    4, float);
DOUBLE_CALLBACK_SETTER_CB(_color4f_setter_cb, 4, float);
DOUBLE_CALLBACK_GETTER   (_dir3d_getter,      3, double);
DOUBLE_CALLBACK_GETTER_CB(_dir3d_getter_cb,   3, double);
DOUBLE_CALLBACK_SETTER   (_dir3d_setter,      3, double);
DOUBLE_CALLBACK_SETTER_CB(_dir3d_setter_cb,   3, double);
DOUBLE_CALLBACK_GETTER   (_quat4d_getter,     4, double);
DOUBLE_CALLBACK_GETTER_CB(_quat4d_getter_cb,  4, double);
DOUBLE_CALLBACK_SETTER   (_quat4d_setter,     4, double);
DOUBLE_CALLBACK_SETTER_CB(_quat4d_setter_cb,  4, double);

void _bootstap(){
  dTHX;
  HV *stash = gv_stashpv("AntTweakBar", TRUE);
  CONSTANT(TW_OPENGL);
  CONSTANT(TW_OPENGL_CORE);
  CONSTANT(TW_DIRECT3D9);
  CONSTANT(TW_DIRECT3D10);
  CONSTANT(TW_DIRECT3D11);

  _type_map = newHV();
  _getters_map = newHV();
  _setters_map = newHV();
  _getters_cb_map = newHV();
  _setters_cb_map = newHV();
  _sv_copy_names = newHV();
  _cb_read_map = newHV();
  _cb_write_map = newHV();
  _cb_marker_map = newHV();

  _add_type("bool", TW_TYPE_BOOL32, _int_getter, _int_setter, _int_getter_cb, _int_setter_cb);
  _add_type("integer", TW_TYPE_INT32,  _int_getter, _int_setter, _int_getter_cb, _int_setter_cb);
  _add_type("number", TW_TYPE_DOUBLE,  _number_getter, _number_setter, _number_getter_cb, _number_setter_cb);
  _add_type("string", TW_TYPE_CDSTRING, _string_getter, _string_setter, _string_getter_cb, _string_setter_cb);
  _add_type("color3f", TW_TYPE_COLOR3F, _color3f_getter, _color3f_setter, _color3f_getter_cb, _color3f_setter_cb);
  _add_type("color4f", TW_TYPE_COLOR4F, _color4f_getter, _color4f_setter, _color4f_getter_cb, _color4f_setter_cb);
  _add_type("direction", TW_TYPE_DIR3D, _dir3d_getter, _dir3d_setter, _dir3d_getter_cb, _dir3d_setter_cb);
  _add_type("quaternion", TW_TYPE_QUAT4D, _quat4d_getter, _quat4d_setter, _quat4d_getter_cb, _quat4d_setter_cb);
}

MODULE = AntTweakBar		PACKAGE = AntTweakBar

BOOT:
_bootstap();

void



( run in 1.340 second using v1.01-cache-2.11-cpan-13bb782fe5a )