/*
	Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/


/*
This example creates three externally defined functions to be available in 
the relations dialog:
	ptk_set_a & ptk_set_b are used from the left-hand side of relations 
                to initialize double values to stored "A" and "B" variables.
	ptk_eval_ax_plus_b returns the computation of Ax+B, where x is an 
                input to the function.

These functions are available only while the Pro/TK application is running.  
Models can be saved with relations referencing these functions, but these 
models will have relation errors if retrieved while the application is not 
running.
*/

#include <ProToolkit.h>
#include <ProRelSet.h>
#include <ProParamval.h>

#define PTK_SET_A "ptk_set_a"
#define PTK_SET_B "ptk_set_b"

static double stored_a;
static double stored_b;

/*==========================================================================*\
FUNCTION: UserRelFPropertySet
PURPOSE:  "Write" function for the assignment of the parameters used for 
           calculation.
\*==========================================================================*/
ProError UserRelFPropertySet (ProRelset* relset, ProMdl mdl,
			      char* ext_func_name,  ProParamvalue* args,
			      ProParamvalue* input, ProAppData data)
{
  if (input->type != PRO_PARAM_DOUBLE)
    return (PRO_TK_GENERAL_ERROR);
  
  if (strcmp (ext_func_name, PTK_SET_A) == 0)
    {
      stored_a = input->value.d_val;
      return (PRO_TK_NO_ERROR);
    }
  
  if (strcmp (ext_func_name, PTK_SET_B) == 0)
    {
      stored_b = input->value.d_val;
      return (PRO_TK_NO_ERROR);
    }
  
  return (PRO_TK_GENERAL_ERROR);
}

/*==========================================================================*\
FUNCTION: UserRelFGetAxPlusB
PURPOSE:  "Read" function for the calculation of the values.
\*==========================================================================*/
ProError UserRelFGetAxPlusB (ProRelset* relset, ProMdl mdl,
			     char* ext_func_name,  ProParamvalue* args,
			     ProAppData data, ProParamvalue* result)
{
  
  double x = args [0].value.d_val;
  
  result->type = PRO_PARAM_DOUBLE;
  result->value.d_val = stored_a * x + stored_b;
  
  return (PRO_TK_NO_ERROR);
}

/*==========================================================================*\
FUNCTION: UserCustomRelFunctionsDefine
PURPOSE:  Define the functions that can be used by Pro/E users in relations.
\*==========================================================================*/
int UserCustomRelFunctionsDefine ()
{
  ProRelfuncArg* args_array;
  
  stored_a = 5.5;
  stored_b = 13.1;
  
/*--------------------------------------------------------------------------*\
  Allocate the array of expected arguments and types for the get function.
\*--------------------------------------------------------------------------*/
  ProArrayAlloc (1, sizeof (ProRelfuncArg), 1, (ProArray*)&args_array);
  args_array [0].type = PRO_PARAM_DOUBLE;
  args_array [0].attributes = PRO_RELF_ATTR_NONE;
  
  
/*--------------------------------------------------------------------------*\
  Register the set functions.  These functions should be used only on the
  LHS of relations, and they do not require or use any arguments.
\*--------------------------------------------------------------------------*/
  ProRelationFunctionRegister ("ptk_set_a", NULL,
			       NULL, UserRelFPropertySet, NULL,
			       PRO_B_TRUE, NULL);
  
  
  ProRelationFunctionRegister ("ptk_set_b", NULL,
			       NULL, UserRelFPropertySet, NULL,
			       PRO_B_TRUE, NULL);

/*--------------------------------------------------------------------------*\
  Register the computation function.  This function should be used only on the
  RHS of relations.  Type-checking is used to ensure that exactly one double
  argument was passed.
\*--------------------------------------------------------------------------*/
  ProRelationFunctionRegister ("ptk_eval_ax_plus_b", args_array,
			       UserRelFGetAxPlusB, NULL, NULL,
			       PRO_B_FALSE, NULL);

  
  return (PRO_TK_NO_ERROR);
}

#undef PTK_SET_A
#undef PTK_SET_B