aqhome-react: read network files.
This commit is contained in:
@@ -42,6 +42,7 @@
|
|||||||
init.h
|
init.h
|
||||||
fini.h
|
fini.h
|
||||||
loop.h
|
loop.h
|
||||||
|
net_read.h
|
||||||
</headers>
|
</headers>
|
||||||
|
|
||||||
<sources>
|
<sources>
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
init.c
|
init.c
|
||||||
fini.c
|
fini.c
|
||||||
loop.c
|
loop.c
|
||||||
|
net_read.c
|
||||||
main.c
|
main.c
|
||||||
</sources>
|
</sources>
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "./init.h"
|
#include "./init.h"
|
||||||
|
#include "./net_read.h"
|
||||||
#include "./aqhome_react_p.h"
|
#include "./aqhome_react_p.h"
|
||||||
#include "aqhome-react/units/u_timer.h"
|
#include "aqhome-react/units/u_timer.h"
|
||||||
#include "aqhome-react/units/u_varchanges.h"
|
#include "aqhome-react/units/u_varchanges.h"
|
||||||
@@ -95,7 +96,7 @@ int AqHomeReact_Init(AQHOME_REACT *aqh, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_setupBuiltinUnits(aqh);
|
AqHomeReact_ReloadUnitNets(aqh);
|
||||||
|
|
||||||
rv=_setupBroker(aqh, dbArgs);
|
rv=_setupBroker(aqh, dbArgs);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
@@ -108,6 +109,29 @@ int AqHomeReact_Init(AQHOME_REACT *aqh, int argc, char **argv)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void AqHomeReact_ReloadUnitNets(AQHOME_REACT *aqh)
|
||||||
|
{
|
||||||
|
AQHREACT_UNIT_NET_LIST *unitNetList;
|
||||||
|
|
||||||
|
AQHREACT_UnitNet_List_Clear(aqh->unitNetList);
|
||||||
|
AQHREACT_Unit_List_Clear(aqh->unitList);
|
||||||
|
aqh->timerUnit=NULL;
|
||||||
|
aqh->varChangeUnit=NULL;
|
||||||
|
|
||||||
|
_setupBuiltinUnits(aqh);
|
||||||
|
|
||||||
|
unitNetList=AQHREACT_ReadUnitNetFiles(aqh);
|
||||||
|
if (unitNetList) {
|
||||||
|
AQHREACT_UnitNet_List_free(aqh->unitNetList);
|
||||||
|
aqh->unitNetList=unitNetList;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DBG_INFO(NULL, "No unit nets read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int _createPidFile(const char *pidFilename)
|
int _createPidFile(const char *pidFilename)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
int AqHomeReact_Init(AQHOME_REACT *aqh, int argc, char **argv);
|
int AqHomeReact_Init(AQHOME_REACT *aqh, int argc, char **argv);
|
||||||
|
|
||||||
|
void AqHomeReact_ReloadUnitNets(AQHOME_REACT *aqh);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
342
apps/aqhome-react/net_read.c
Normal file
342
apps/aqhome-react/net_read.c
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* This file is part of the project AqHome.
|
||||||
|
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||||
|
*
|
||||||
|
* The license for this file can be found in the file COPYING which you
|
||||||
|
* should have received along with this file.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "./net_read.h"
|
||||||
|
#include "aqhome-react/types/unit.h"
|
||||||
|
#include "aqhome-react/types/unitnet.h"
|
||||||
|
|
||||||
|
#include "aqhome/aqhome.h"
|
||||||
|
|
||||||
|
#include <gwenhywfar/xml.h>
|
||||||
|
#include <gwenhywfar/text.h>
|
||||||
|
#include <gwenhywfar/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* forward declarations
|
||||||
|
* ------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
AQHREACT_UNIT_NET_LIST *_readUnitNetFiles(AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl);
|
||||||
|
static int _readUnitNetFileToList(AQHOME_REACT *aqh, const char *sFilename, AQHREACT_UNIT_NET_LIST *unitNetList);
|
||||||
|
static AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetNode);
|
||||||
|
static AQHREACT_UNIT *_readUnit(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNode);
|
||||||
|
static int _readParam(AQHREACT_UNIT *unit, GWEN_XMLNODE *n);
|
||||||
|
static int _readLink(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *linkNode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* implementations
|
||||||
|
* ------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
AQHREACT_UNIT_NET_LIST *AQHREACT_ReadUnitNetFiles(AQHOME_REACT *aqh)
|
||||||
|
{
|
||||||
|
GWEN_STRINGLIST *sl;
|
||||||
|
|
||||||
|
sl=AQH_GetListOfMatchingDataFiles("aqhome/react/networks", "*.xml");
|
||||||
|
if (sl) {
|
||||||
|
AQHREACT_UNIT_NET_LIST *unitNetList;
|
||||||
|
|
||||||
|
unitNetList=_readUnitNetFiles(aqh, sl);
|
||||||
|
GWEN_StringList_free(sl);
|
||||||
|
if (unitNetList==NULL) {
|
||||||
|
DBG_INFO(NULL, "Error reading unit network files");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return unitNetList;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DBG_ERROR(NULL, "No unit network files");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AQHREACT_UNIT_NET_LIST *_readUnitNetFiles(AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl)
|
||||||
|
{
|
||||||
|
GWEN_STRINGLISTENTRY *se;
|
||||||
|
AQHREACT_UNIT_NET_LIST *unitNetList;
|
||||||
|
|
||||||
|
unitNetList=AQHREACT_UnitNet_List_new();
|
||||||
|
se=GWEN_StringList_FirstEntry(sl);
|
||||||
|
while(se) {
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
s=GWEN_StringListEntry_Data(se);
|
||||||
|
if (s && *s) {
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
DBG_INFO(NULL, "Reading unit network file \"%s\"", s);
|
||||||
|
rv=_readUnitNetFileToList(aqh, s, unitNetList);
|
||||||
|
if (rv<0 && rv!=GWEN_ERROR_NO_DATA) {
|
||||||
|
DBG_WARN(NULL, "Error reading unit network file \"%s\" (%d), ignoring", s, rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
se=GWEN_StringListEntry_Next(se);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AQHREACT_UnitNet_List_GetCount(unitNetList)<1) {
|
||||||
|
AQHREACT_UnitNet_List_free(unitNetList);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return unitNetList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int _readUnitNetFileToList(AQHOME_REACT *aqh, const char *sFilename, AQHREACT_UNIT_NET_LIST *unitNetList)
|
||||||
|
{
|
||||||
|
GWEN_XMLNODE *rootNode;
|
||||||
|
GWEN_XMLNODE *netListNode;
|
||||||
|
GWEN_XMLNODE *netNode;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rootNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, NULL);
|
||||||
|
rv=GWEN_XML_ReadFile(rootNode, sFilename, GWEN_XML_FLAGS_DEFAULT);
|
||||||
|
if (rv<0) {
|
||||||
|
DBG_ERROR(NULL, "Error reading XML file \"%s\": %d", sFilename, rv);
|
||||||
|
GWEN_XMLNode_free(rootNode);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
netListNode=GWEN_XMLNode_FindFirstTag(rootNode, "networks", NULL, NULL);
|
||||||
|
if (netListNode==NULL)
|
||||||
|
netListNode=rootNode;
|
||||||
|
|
||||||
|
netNode=GWEN_XMLNode_FindFirstTag(netListNode, "network", NULL, NULL);
|
||||||
|
while(netNode) {
|
||||||
|
AQHREACT_UNIT_NET *unitNet;
|
||||||
|
|
||||||
|
unitNet=_readUnitNetFromXml(aqh, netNode);
|
||||||
|
if (unitNet)
|
||||||
|
AQHREACT_UnitNet_List_Add(unitNet, unitNetList);
|
||||||
|
else {
|
||||||
|
DBG_ERROR(NULL, "Error loading network from file \"%s\", ignoring.", sFilename);
|
||||||
|
}
|
||||||
|
netNode=GWEN_XMLNode_FindNextTag(netNode, "network", NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetNode)
|
||||||
|
{
|
||||||
|
AQHREACT_UNIT_NET *unitNet;
|
||||||
|
const char *s;
|
||||||
|
GWEN_XMLNODE *nGroup;
|
||||||
|
|
||||||
|
unitNet=AQHREACT_UnitNet_new();
|
||||||
|
s=GWEN_XMLNode_GetProperty(unitNetNode, "id", NULL);
|
||||||
|
AQHREACT_UnitNet_SetName(unitNet, s);
|
||||||
|
|
||||||
|
nGroup=GWEN_XMLNode_FindFirstTag(unitNetNode, "units", NULL, NULL);
|
||||||
|
if (nGroup) {
|
||||||
|
GWEN_XMLNODE *n;
|
||||||
|
|
||||||
|
n=GWEN_XMLNode_FindFirstTag(nGroup, "unit", NULL, NULL);
|
||||||
|
while(n) {
|
||||||
|
AQHREACT_UNIT *unit;
|
||||||
|
|
||||||
|
unit=_readUnit(aqh, n);
|
||||||
|
if (unit)
|
||||||
|
AQHREACT_UnitNet_AddUnit(unitNet, unit);
|
||||||
|
else {
|
||||||
|
DBG_ERROR(NULL, "Error reading unit in net \"%s\"", AQHREACT_UnitNet_GetName(unitNet));
|
||||||
|
AQHREACT_UnitNet_free(unitNet);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
n=GWEN_XMLNode_FindNextTag(n, "unit", NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nGroup=GWEN_XMLNode_FindFirstTag(unitNetNode, "links", NULL, NULL);
|
||||||
|
if (nGroup) {
|
||||||
|
GWEN_XMLNODE *n;
|
||||||
|
|
||||||
|
n=GWEN_XMLNode_FindFirstTag(nGroup, "link", NULL, NULL);
|
||||||
|
while(n) {
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv=_readLink(aqh, unitNet, n);
|
||||||
|
if (rv<0) {
|
||||||
|
DBG_ERROR(NULL, "Error reading link in net \"%s\" (%d)", AQHREACT_UnitNet_GetName(unitNet), rv);
|
||||||
|
AQHREACT_UnitNet_free(unitNet);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
n=GWEN_XMLNode_FindNextTag(n, "link", NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unitNet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AQHREACT_UNIT *_readUnit(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNode)
|
||||||
|
{
|
||||||
|
AQHREACT_UNIT *unit;
|
||||||
|
const char *unitType;
|
||||||
|
const char *unitId;
|
||||||
|
GWEN_XMLNODE *nGroup;
|
||||||
|
|
||||||
|
unitType=GWEN_XMLNode_GetProperty(unitNode, "type", NULL);
|
||||||
|
if (!(unitType && *unitType)) {
|
||||||
|
DBG_ERROR(NULL, "No type name in unit node");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
unit=AqHomeReact_CreateUnitByName(aqh, unitType);
|
||||||
|
|
||||||
|
unitId=GWEN_XMLNode_GetProperty(unitNode, "id", NULL);
|
||||||
|
AQHREACT_Unit_SetId(unit, unitId);
|
||||||
|
|
||||||
|
nGroup=GWEN_XMLNode_FindFirstTag(unitNode, "params", NULL, NULL);
|
||||||
|
if (nGroup) {
|
||||||
|
GWEN_XMLNODE *n;
|
||||||
|
|
||||||
|
n=GWEN_XMLNode_FindFirstTag(nGroup, "param", NULL, NULL);
|
||||||
|
while(n) {
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv=_readParam(unit, n);
|
||||||
|
if (rv<0) {
|
||||||
|
DBG_INFO(NULL, "here (%d)", rv);
|
||||||
|
AQHREACT_Unit_free(unit);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
n=GWEN_XMLNode_FindNextTag(n, "param", NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int _readParam(AQHREACT_UNIT *unit, GWEN_XMLNODE *paramNode)
|
||||||
|
{
|
||||||
|
const char *paramName;
|
||||||
|
|
||||||
|
paramName=GWEN_XMLNode_GetProperty(paramNode, "name", NULL);
|
||||||
|
if (paramName && *paramName) {
|
||||||
|
AQHREACT_PARAM *param;
|
||||||
|
|
||||||
|
param=AQHREACT_Unit_GetParamByName(unit, paramName);
|
||||||
|
if (param) {
|
||||||
|
const char *value;
|
||||||
|
|
||||||
|
value=GWEN_XMLNode_GetCharValue(paramNode, NULL, NULL);
|
||||||
|
if (value && *value) {
|
||||||
|
int dataType;
|
||||||
|
|
||||||
|
dataType=AQHREACT_Param_GetDataType(param);
|
||||||
|
switch(dataType) {
|
||||||
|
case AQHREACT_DATAOBJECTTYPE_DOUBLE:
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
double valueAsDouble;
|
||||||
|
|
||||||
|
rv=GWEN_Text_StringToDouble(value, &valueAsDouble);
|
||||||
|
if (rv<0) {
|
||||||
|
DBG_ERROR(NULL, "Not a DOUBLE value for param %s in unit %s [%s]", paramName, AQHREACT_Unit_GetId(unit), value);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
AQHREACT_Param_SetDoubleValue(param, valueAsDouble);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AQHREACT_DATAOBJECTTYPE_STRING:
|
||||||
|
default:
|
||||||
|
AQHREACT_Param_SetStringValue(param, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DBG_ERROR(NULL, "No param name \"%s\" in unit %s", paramName, AQHREACT_Unit_GetId(unit));
|
||||||
|
return GWEN_ERROR_BAD_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int _readLink(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *linkNode)
|
||||||
|
{
|
||||||
|
const char *sourceUnitName;
|
||||||
|
const char *sourceSlotName;
|
||||||
|
const char *targetUnitName;
|
||||||
|
const char *targetSlotName;
|
||||||
|
AQHREACT_UNIT *sourceUnit;
|
||||||
|
AQHREACT_UNIT *targetUnit;
|
||||||
|
AQHREACT_INPUT_SLOT *inputSlot;
|
||||||
|
AQHREACT_OUTPUT_SLOT *outputSlot;
|
||||||
|
AQHREACT_LINK *link;
|
||||||
|
|
||||||
|
sourceUnitName=GWEN_XMLNode_GetProperty(linkNode, "sourceUnit", NULL);
|
||||||
|
sourceSlotName=GWEN_XMLNode_GetProperty(linkNode, "sourceSlot", NULL);
|
||||||
|
targetUnitName=GWEN_XMLNode_GetProperty(linkNode, "targetUnit", NULL);
|
||||||
|
targetSlotName=GWEN_XMLNode_GetProperty(linkNode, "targetSlot", NULL);
|
||||||
|
|
||||||
|
if (!(sourceUnitName && *sourceUnitName && sourceSlotName && *sourceSlotName &&
|
||||||
|
targetUnitName && *targetUnitName && targetSlotName && *targetSlotName)) {
|
||||||
|
DBG_ERROR(NULL,
|
||||||
|
"Link in net \"%s\" needs properties sourceUnit, sourceSlot, targetUnit and targetSlot",
|
||||||
|
AQHREACT_UnitNet_GetName(unitNet));
|
||||||
|
return GWEN_ERROR_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceUnit=AQHREACT_UnitNet_GetUnitById(unitNet, sourceUnitName);
|
||||||
|
if (sourceUnit==NULL)
|
||||||
|
sourceUnit=AqHomeReact_FindUnitByNetNameAndUnitId(aqh, NULL, sourceUnitName);
|
||||||
|
if (sourceUnit==NULL) {
|
||||||
|
DBG_ERROR(NULL, "Source unit \"%s\" not found", sourceUnitName);
|
||||||
|
return GWEN_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
outputSlot=AQHREACT_Unit_GetOutputSlotByName(sourceUnit, sourceSlotName);
|
||||||
|
if (outputSlot==NULL) {
|
||||||
|
DBG_ERROR(NULL, "Output slot \"%s\" not found for source unit \"%s\"", sourceSlotName, sourceUnitName);
|
||||||
|
return GWEN_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetUnit=AQHREACT_UnitNet_GetUnitById(unitNet, targetUnitName);
|
||||||
|
if (targetUnit==NULL)
|
||||||
|
targetUnit=AqHomeReact_FindUnitByNetNameAndUnitId(aqh, NULL, targetUnitName);
|
||||||
|
if (targetUnit==NULL) {
|
||||||
|
DBG_ERROR(NULL, "Target unit \"%s\" not found", targetUnitName);
|
||||||
|
return GWEN_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
inputSlot=AQHREACT_Unit_GetOrCreateUnusedInputSlotByName(targetUnit, targetSlotName);
|
||||||
|
if (inputSlot==NULL) {
|
||||||
|
DBG_ERROR(NULL, "Input slot \"%s\" not found for target unit \"%s\"", targetSlotName, targetUnitName);
|
||||||
|
return GWEN_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
link=AQHREACT_Link_new();
|
||||||
|
AQHREACT_Link_SetTargetUnitId(link, targetUnitName);
|
||||||
|
AQHREACT_Link_SetTargetUnit(link, targetUnit);
|
||||||
|
AQHREACT_Link_SetTargetInputSlotIdForUnit(link, AQHREACT_InputSlot_GetIdForUnit(inputSlot));
|
||||||
|
AQHREACT_OutputSlot_AddLink(outputSlot, link);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
21
apps/aqhome-react/net_read.h
Normal file
21
apps/aqhome-react/net_read.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* This file is part of the project AqHome.
|
||||||
|
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||||
|
*
|
||||||
|
* The license for this file can be found in the file COPYING which you
|
||||||
|
* should have received along with this file.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef AQHOMEREACT_NET_READ_H
|
||||||
|
#define AQHOMEREACT_NET_READ_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "./aqhome_react.h"
|
||||||
|
|
||||||
|
|
||||||
|
AQHREACT_UNIT_NET_LIST *AQHREACT_ReadUnitNetFiles(AQHOME_REACT *aqh);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -65,6 +65,7 @@ AQHREACT_INPUT_SLOT_LIST *AQHREACT_Unit_GetInputSlots(const AQHREACT_UNIT *unit)
|
|||||||
void AQHREACT_Unit_AddInputSlot(AQHREACT_UNIT *unit, AQHREACT_INPUT_SLOT *inSlot);
|
void AQHREACT_Unit_AddInputSlot(AQHREACT_UNIT *unit, AQHREACT_INPUT_SLOT *inSlot);
|
||||||
AQHREACT_INPUT_SLOT *AQHREACT_Unit_GetInputSlotByIdForUnit(const AQHREACT_UNIT *unit, int id);
|
AQHREACT_INPUT_SLOT *AQHREACT_Unit_GetInputSlotByIdForUnit(const AQHREACT_UNIT *unit, int id);
|
||||||
AQHREACT_INPUT_SLOT *AQHREACT_Unit_GetInputSlotByName(const AQHREACT_UNIT *unit, const char *s);
|
AQHREACT_INPUT_SLOT *AQHREACT_Unit_GetInputSlotByName(const AQHREACT_UNIT *unit, const char *s);
|
||||||
|
AQHREACT_INPUT_SLOT *AQHREACT_Unit_GetOrCreateUnusedInputSlotByName(AQHREACT_UNIT *unit, const char *s);
|
||||||
|
|
||||||
|
|
||||||
AQHREACT_OUTPUT_SLOT_LIST *AQHREACT_Unit_GetOutputSlots(const AQHREACT_UNIT *unit);
|
AQHREACT_OUTPUT_SLOT_LIST *AQHREACT_Unit_GetOutputSlots(const AQHREACT_UNIT *unit);
|
||||||
|
|||||||
Reference in New Issue
Block a user