3 weeks ago - last edited 2 weeks ago
I am reworking archicad 28 MEP addon for my needs. Is there any chance i can get some sample code for MEP input interface? In example all i found is mep functions but without input interface like place a point and draw rubber line. (there is interface_functions example with point input, line, polygon etc but lacks for typical MEP) For tracker i found tracker menager sample and found in documentation how to create new trakcer item which i think i am starting to understand.
I created some pretty basic input interface with rubber line snaping to angles etc but there i a lot of work to do to get it complete for usage (pet palette, trackers and much much more) and meabe there is a chance i could save time but just getting some example code for rework. In general concept of what is build in in archicad is good but it lacks here and there for my case of use. Same goes for MEP functions which are pretty limited and for me it doesnt fit and callback apparently doesnt help either becouse i cant change dimensions and bench angle to my neeeds becouse it is limited to referenceID's which are linked to build in category of dimensions. So whats even the point of this whole callback whole mep when u literally cant even change anything.
If there is any chance for this interface functions i can even contact you through our IT department which bought licences. This is must have for me 😉 Just let me know. And in fact with MEP limitations i dont even think it is possible to input dimmensions like 17mm so do i cant add code for oval ducts becouse source code for creating circual or rectangular objects are hidden in binnary code...
2 weeks ago - last edited 2 weeks ago
If not meabe there atleast chance for some tips on tracker setup. So far i have this but tracker doesnt show up 😞 any tips?
// Tracker
#include "ITrackerItem.hpp"
#include "Tracker.hpp"
#include "ACAPI/TrackerManager.hpp"
using namespace ACAPI::Tracking::v1;
// Przechowywanie wskaźnika na tracker
static Tracking::Tracker *globalTracker = nullptr;
class MyCustomTrackerItem : public Tracking::ITrackerItem
{
private:
GS::UniString label;
GS::UniString value;
public:
MyCustomTrackerItem(const GS::UniString &label, const GS::UniString &value)
: label(label), value(value) {}
~MyCustomTrackerItem() override {}
void UpdateValue(const GS::UniString &newValue)
{
value = newValue;
}
GS::UniString GetToolTipText() const override
{
return label + ": " + value;
}
short GetHeight() const override
{
return 20; // Wysokość w pikselach
}
bool IsInInput() const override { return true; }
bool IsVisible() const override { return true; }
bool IsEnabled() const override { return true; }
bool AcceptEnabled() const override { return false; }
bool ReturnToRunningEnabled() const override { return false; }
// Puste funkcje, nieużywane w tym przykładzie
void SetParent(Tracking::Tracker &tracker) override {}
void ClearParent() override {}
void Draw(NewDisplay::NativeContext &context, const DG::Rect &itemRect, bool selected, short itemWidth[4]) override {}
void Synchronize() const override {}
DG::Item *ActivateEditMode(DG::Palette &palette, short itemWidth[4]) override { return nullptr; }
void DeactivateEditMode() override {}
short GetColumnWidth(short (&itemWidth)[4]) const override { return 0; }
DG::Rect GetActiveRectFromPoint(DG::Point point, short itemWidth[4], GS::UniString &toolTip) const override
{
return DG::Rect();
}
void FocusDefaultItem() override {}
DG::Icon GetExtraIcon(short &width, short &height) const override { return DG::Icon(); }
void ExtraIconClicked() override {}
};
static void InitCustomTracker()
{
// Uzyskanie menadżera Trackera
auto managerResult = ACAPI::Tracking::GetTrackerManager();
if (managerResult.IsErr())
{
DBPrintf("Nie udało się uzyskać menadżera Trackera.\n");
return;
}
auto trackerManager = managerResult.Unwrap();
auto trackerRefResult = trackerManager.GetMainTracker();
if (trackerRefResult.IsErr())
{
DBPrintf("Nie udało się uzyskać głównego Trackera.\n");
return;
}
// Rozpakowanie referencji i przypisanie wskaźnika
globalTracker = &trackerRefResult.Unwrap().get();
// Dodanie niestandardowego elementu Trackera
auto customItem = new MyCustomTrackerItem("Długość", "0 mm");
globalTracker->AddItem(customItem);
globalTracker->Show();
}
static void UpdateCustomTracker(const GS::UniString &distanceText)
{
if (globalTracker == nullptr)
{
DBPrintf("Globalny tracker jest niezainicjalizowany.\n");
return;
}
// Pobranie widocznego elementu
auto item = globalTracker->EnumerateVisibleItems();
if (item == nullptr)
{
DBPrintf("Nie znaleziono widocznych elementów trackera.\n");
return;
}
// Oczekiwanie, że item jest wskaźnikiem na Tracking::ITrackerItem
if (*item == nullptr)
{
DBPrintf("Nie znaleziono widocznych elementów trackera.\n");
return;
}
// Próbujemy rzutować na MyCustomTrackerItem
if (auto *customItem = dynamic_cast<MyCustomTrackerItem *>(*item))
{
customItem->UpdateValue(distanceText);
}
else
{
DBPrintf("Element trackera nie jest typu MyCustomTrackerItem.\n");
}
}
void CreateCustomTracker()
{
InitCustomTracker();
UpdateCustomTracker("100 mm");
}
static void RubberLineCallBack(const API_RubberLineInfo *info)
{
API_RubberLineType rubberLine;
// Wyzerowanie struktury linii pomocniczej
BNZeroMemory(&rubberLine, sizeof(API_RubberLineType));
// Przechodzimy przez wszystkie punkty w wektorze
if (theCoords.size() >= 2)
{
for (size_t i = 1; i < theCoords.size(); ++i)
{
rubberLine.c1.x = theCoords[i - 1].x;
rubberLine.c1.y = theCoords[i - 1].y;
rubberLine.c1.z = theCoords[i - 1].z;
rubberLine.c2.x = theCoords[i].x;
rubberLine.c2.y = theCoords[i].y;
rubberLine.c2.z = theCoords[i].z;
ACAPI_UserInput_DrawRubberLine(&rubberLine);
}
}
rubberLine.c1.x = theCoords[theCoords.size() - 1].x;
rubberLine.c1.y = theCoords[theCoords.size() - 1].y;
rubberLine.c1.z = theCoords[theCoords.size() - 1].z;
rubberLine.c2.x = info->actCoord.x;
rubberLine.c2.y = info->actCoord.y;
rubberLine.c2.z = info->actCoord.z;
// Rysowanie linii pomocniczej
ACAPI_UserInput_DrawRubberLine(&rubberLine);
// Obliczanie odległości i aktualizacja trackera
double distance = sqrt(pow(rubberLine.c2.x - rubberLine.c1.x, 2) +
pow(rubberLine.c2.y - rubberLine.c1.y, 2));
GS::UniString distanceText = GS::UniString::Printf("%.2f mm", distance);
UpdateCustomTracker(distanceText);
}
// -----------------------------------------------------------------------------
// Function to get input from user :
// -----------------------------------------------------------------------------
// Funkcja do dodawania punktu
void AddCoordPoint(API_Coord3D point)
{
theCoords.push_back(point); // Dodajemy punkt do wektora
}
// Funkcja do kasowania ostatniego punktu
void RemoveLastCoordPoint()
{
if (!theCoords.empty())
{
theCoords.pop_back(); // Usuwa ostatni punkt
}
else
{
printf("Brak punktów do usunięcia!\n");
}
}
// Funkcja do czyszczenia wektora
void ClearCoordPoints()
{
theCoords.clear(); // Usuwa wszystkie punkty z wektora
theCoords.shrink_to_fit(); // Zmniejsza pojemność wektora, jeśli to możliwe
}
// Funkcja do dostępu i wyświetlania wszystkich punktów
void DisplayCoords()
{
for (size_t i = 0; i < theCoords.size(); i++)
{
printf("Punkt %zu: (%f, %f, %f)\n", i + 1, theCoords[i].x, theCoords[i].y, theCoords[i].z);
}
}
// Funkcja obliczająca odległość między dwoma ostatnimi punktami 3D i sprawdzająca, czy są blisko siebie
bool AreLastTwoPointsClose(double tolerance = 0.001)
{
if (theCoords.size() < 2)
{
return false; // Muszą być co najmniej dwa punkty, aby to sprawdzić
}
// Pobierz ostatni i przedostatni punkt
const API_Coord3D &lastPoint = theCoords.back(); // Ostatni punkt
const API_Coord3D &secondLastPoint = theCoords[theCoords.size() - 2]; // Przedostatni punkt
// Obliczenie odległości euklidesowej
double dx = lastPoint.x - secondLastPoint.x;
double dy = lastPoint.y - secondLastPoint.y;
double dz = lastPoint.z - secondLastPoint.z;
// Obliczenie odległości
double distance = sqrt(dx * dx + dy * dy + dz * dz);
// Jeśli odległość jest mniejsza niż tolerancja, to punkty są blisko siebie
return distance < tolerance;
}