ADTF_DISPLAY_TOOLBOX  3.8.0 (ADTF 3.14.3)
Source Code for Demo 2D Shape Drawer
Location
./src/examples/src/shapedrawer
This example shows:
  • how to create a custom drawer.
  • how to use DDL or structs to describe shapes\
  • how to use the canvas inside the Draw method.
Header
#pragma once
#undef GetObject
#include <adtffiltersdk/filter.h>
#include <adtf_base.h>
#include "shape_enum.h"
#include "shape_struct.h"
class cShapeDrawer :
public adtf::ucom::object<adtf::disptb::drawerlib::cDrawer>
{
public:
ADTF_CLASS_ID_NAME(
cShapeDrawer,
"demo_shape.2d_drawer.disptb.cid",
"Demo 2D Shape Drawer"
);
cShapeDrawer();
~cShapeDrawer() = default;
tResult ProcessInput(adtf::base::tNanoSeconds tmTrigger, adtf::streaming::ISampleReader* pReader) override;
tResult Draw(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas) override;
private:
tResult PaintShape(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas, const tShapeStruct& oShape);
private:
adtf::streaming::ISampleReader* m_pReader = nullptr;
adtf::util::lock_free_queue<tShapeStruct> m_oShapes;
};
Copyright © Audi Electronics Venture GmbH.
#pragma once
#include <adtf_base.h>
#include <adtffiltersdk/filter.h>
enum tShapeType : tUInt
{
eShapeLines = 0,
eShapeQuads = 1
};
#pragma once
#include <adtffiltersdk/filter.h>
#include "shape_enum.h"
class cShapeGenerator : public adtf::filter::cFilter
{
public:
ADTF_CLASS_ID_NAME(cShapeGenerator,
"create_shapes.filter.disptb.cid"; ,
"Demo Shape Generator Filter");
public:
cShapeGenerator();
tResult Process(adtf::base::tNanoSeconds tmTimeOfTrigger, adtf::streaming::IRunner* pRunner) override;
private:
adtf::streaming::ISampleWriter* m_pWriter = nullptr;
adtf::base::property_variable<tUInt> m_nShapeLineCount = 10;
adtf::base::property_variable<tUInt> m_nShapeLineLength = 200;
adtf::base::property_variable<tUInt> m_nShapeLineOffset = 20;
adtf::base::property_variable<tUInt> m_nShapeQuadCount = 4;
adtf::base::property_variable<tUInt> m_nShapeQuadHeight = 50;
adtf::base::property_variable<tUInt> m_nShapeQuadWidth = 50;
adtf::base::property_variable<tUInt> m_nShapeQuadOffset = 100;
adtf::base::property_variable<tUInt> m_nShapeColorRed = 255;
adtf::base::property_variable<tUInt> m_nShapeColorGreen = 0;
adtf::base::property_variable<tUInt> m_nShapeColorBlue = 0;
adtf::base::property_variable<tShapeType> m_nShapeType = eShapeLines;
};
Implementation
#include "shape_drawer.h"
#include "shape_struct.h"
using namespace adtf::util;
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::mediadescription;
using namespace adtf::disptb::graphicslib;
cShapeDrawer::cShapeDrawer()
{
SetDescription("Use this Drawer to paint a shape onto the canvas.");
SetHelpLink("$(ADTF_DISPLAY_TOOLBOX_DIR)/doc/displaytoolbox_html/page_2d_shape_drawer_readme.html");
m_pReader = CreateInputPin("shape_input", description<tShapeStruct>());
SetDescription("shape_input", "Incoming shape to draw.");
}
tResult cShapeDrawer::ProcessInput(tNanoSeconds /*tmTrigger*/, ISampleReader* /*pReader*/)
{
object_ptr<const ISample> pSample;
if (IS_OK(m_pReader->GetLastSample(pSample)))
{
auto oData = sample_data<tShapeStruct>(pSample).GetData();
m_oShapes.Push(oData);
}
RETURN_NOERROR;
}
tResult cShapeDrawer::Draw(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas)
{
tResult nResult;
tShapeStruct oShape;
while (IS_OK(m_oShapes.Pop(&oShape)))
{
pCanvas->PushMatrix();
nResult = PaintShape(pCanvas, oShape);
if (IS_FAILED(nResult))
{
LOG_RESULT(nResult);
break;
}
pCanvas->PopMatrix();
}
RETURN_NOERROR;
}
tResult cShapeDrawer::PaintShape(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas, const tShapeStruct& oShape)
{
cPoint oShapePos(static_cast<tInt>(oShape.x), static_cast<tInt>(oShape.y));
tFloat fAngle = oShape.yaw / (cStdMath::MATH_PI / 180.0);
// set the rotation to the OpenGL matrix
pCanvas->Rotate(fAngle, 0.0f, 0.0f, 1.0f);
// set the color for current shape
pCanvas->Color(oShape.red, oShape.green, oShape.blue, oShape.alpha);
switch (oShape.type)
{
case eShapeLines:
{
if (std::modulus<tUInt>()(oShape.numCoords, 3) != 0)
{
RETURN_ERROR_DESC(ERR_UNEXPECTED, "When drawing lines the number of coordinates n must be n mod 3 = 0");
}
cPoint oStartPoint;
cPoint oEndPoint;
tUInt nCount = 0;
while (nCount < oShape.numCoords)
{
oStartPoint.SetX(static_cast<tInt>(oShape.coords[nCount++].coord));
oStartPoint.SetY(static_cast<tInt>(oShape.coords[nCount++].coord));
nCount++; // skip z
oEndPoint.SetX(static_cast<tInt>(oShape.coords[nCount++].coord));
oEndPoint.SetY(static_cast<tInt>(oShape.coords[nCount++].coord));
nCount++; // skip z
pCanvas->DrawLine(&oStartPoint, &oEndPoint);
}
break;
}
case eShapeQuads:
{
if (std::modulus<tUInt>()(oShape.numCoords, 4) != 0)
{
RETURN_ERROR_DESC(ERR_UNEXPECTED, "When drawing quads the number of coordinates n must be n mod 4 = 0");
}
std::array<IPoint*, 4> oPoints;
tUInt nCount = 0;
while (nCount < oShape.numCoords)
{
for (tSize i = 0; i < 4; i++)
{
oPoints[i] = new cPoint(
static_cast<tInt>(oShape.coords[nCount++].coord),
static_cast<tInt>(oShape.coords[nCount++].coord));
nCount++; // skip z
}
pCanvas->FillPolygon(oPoints.data(), 4);
for (auto& pPoint : oPoints)
{
delete pPoint;
pPoint = nullptr;
}
}
break;
}
default:
RETURN_ERROR_DESC(ERR_UNEXPECTED, "Received unexprected shape enum");
}
RETURN_NOERROR;
}
#include "createshapes_filter.h"
#include "shape_struct.h"
using namespace adtf::streaming;
using namespace adtf::mediadescription;
using namespace adtf::base;
cShapeGenerator::cShapeGenerator()
{
m_nShapeType.SetValueList({ {eShapeLines, "Lines"}, {eShapeQuads, "Quads"} });
m_nShapeType.SetDescription("Selection for the shape type.");
RegisterPropertyVariable("shape/type", m_nShapeType);
m_nShapeLineCount.SetDescription("Defintion for the amount of lines to draw (if selected).");
RegisterPropertyVariable("shape/line/count", m_nShapeLineCount);
m_nShapeLineLength.SetDescription("Defintion for the line length.");
RegisterPropertyVariable("shape/line/length", m_nShapeLineLength);
m_nShapeLineOffset.SetDescription("Defintion for the offset between the lines.");
RegisterPropertyVariable("shape/line/offset", m_nShapeLineOffset);
m_nShapeQuadCount.SetDescription("Defintion for the amount of quads to draw (if selected).");
RegisterPropertyVariable("shape/quad/count", m_nShapeQuadCount);
m_nShapeQuadWidth.SetDescription("Defitnion for the width of the quads.");
RegisterPropertyVariable("shape/quad/width", m_nShapeQuadWidth);
m_nShapeQuadHeight.SetDescription("Defitnion for the width of the quads.");
RegisterPropertyVariable("shape/quad/height", m_nShapeQuadHeight);
m_nShapeQuadOffset.SetDescription("Defitnion for offset between the quads.");
RegisterPropertyVariable("shape/quad/offset", m_nShapeQuadOffset);
m_nShapeColorRed.SetValidRange(0, 255);
m_nShapeColorRed.SetDescription("Red content of the color to draw.");
RegisterPropertyVariable("shape/color/red", m_nShapeColorRed);
m_nShapeColorGreen.SetValidRange(0, 255);
m_nShapeColorGreen.SetDescription("Green content of the color to draw.");
RegisterPropertyVariable("shape/color/green", m_nShapeColorGreen);
m_nShapeColorBlue.SetValidRange(0, 255);
m_nShapeColorBlue.SetDescription("Blue content of the color to draw.");
RegisterPropertyVariable("shape/color/blue", m_nShapeColorBlue);
CreateRunner("shape_trigger", cTimerTriggerHint(std::chrono::milliseconds{ 10 }));
SetDescription("shape_trigger", "Runner to periodically trigger the function which generates the shapes.");
m_pWriter = CreateOutputPin("shape_output", description<tShapeStruct>());
SetDescription("shape_output", "Output pin for generated shapes.");
SetDescription("Use this Filter to generate shapes that can be drawn by the shape_drawer example.");
SetHelpLink("$(ADTF_DISPLAY_TOOLBOX_DIR)/doc/displaytoolbox_html/page_2d_shape_drawer_readme.html");
}
tResult cShapeGenerator::Process(tNanoSeconds tmTimeOfTrigger, IRunner* /*pRunner*/)
{
output_sample_data<tShapeStruct> oShape(tmTimeOfTrigger);
oShape->type = m_nShapeType;
oShape->clearBefore = tFalse;
oShape->roll = 0.0;
oShape->pitch = 0.0;
oShape->yaw = 0.0;
oShape->x = 0.0;
oShape->y = 0.0;
oShape->z = 0.0;
oShape->red = m_nShapeColorRed;
oShape->green = m_nShapeColorGreen;
oShape->blue = m_nShapeColorBlue;
oShape->alpha = 0;
switch (m_nShapeType)
{
case eShapeLines:
{
tUInt nCounter = 0;
tInt nCoord = 0;
for (tSize i = 0; i < m_nShapeLineCount; i++)
{
// start
oShape->coords[nCounter++].coord = nCoord; // x
oShape->coords[nCounter++].coord = nCoord; // y
oShape->coords[nCounter++].coord = -1; // z is unused just push back -1
// end
oShape->coords[nCounter++].coord = nCoord + m_nShapeLineLength; // x
oShape->coords[nCounter++].coord = nCoord; // y
oShape->coords[nCounter++].coord = -1; // z is unused just push back -1
// add offset to next line
nCoord += m_nShapeLineOffset;
}
oShape->numCoords = nCounter;
break;
}
case eShapeQuads:
{
tUInt nCounter = 0;
tInt nCoord = 0;
for (tSize i = 0; i < m_nShapeQuadCount; i++)
{
oShape->coords[nCounter++].coord = nCoord; // p1.x
oShape->coords[nCounter++].coord = nCoord; // p1.y
oShape->coords[nCounter++].coord = -1; // z is unused just push back -1
oShape->coords[nCounter++].coord = nCoord + m_nShapeQuadWidth; // p2.x
oShape->coords[nCounter++].coord = nCoord; // p2.y
oShape->coords[nCounter++].coord = -1; // z is unused just push back -1
oShape->coords[nCounter++].coord = nCoord + m_nShapeQuadWidth; // p3.x
oShape->coords[nCounter++].coord = nCoord + m_nShapeQuadHeight; // p3.y
oShape->coords[nCounter++].coord = -1; // z is unused just push back -1
oShape->coords[nCounter++].coord = nCoord; // p3.x
oShape->coords[nCounter++].coord = nCoord + m_nShapeQuadHeight; // p3.y
oShape->coords[nCounter++].coord = -1; // z is unused just push back -1
nCoord += m_nShapeQuadOffset;
}
oShape->numCoords = nCounter;
break;
}
default:
RETURN_ERROR(ERR_UNEXPECTED);
}
m_pWriter->Write(oShape.Release());
RETURN_NOERROR;
}
#include "shape_drawer.h"
#include "createshapes_filter.h"
ADTF_PLUGIN_VERSION("Demo 2D Shape Drawer Plugin",
disptb,
DISPTB_VERSION_MAJOR,
DISPTB_VERSION_MINOR,
DISPTB_VERSION_PATCH,
cShapeDrawer,
cShapeGenerator)