//////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2025 Autodesk, Inc.  All rights reserved.
//
//  Use of this software is subject to the terms of the Autodesk license 
//  agreement provided at the time of installation or download, or which 
//  otherwise accompanies this software in either electronic or hard copy form.   
//
//////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"

//AcadM
//////////////////////////////////////////////////////////////////////////
//You must add the following lines before including the "acm.h" file
//1. import defines for AmgDim crx module 
#define ACMSYMBB_CRX_DLLSHARE
#define ACMSYMBB_CRX_DLLSHARE_DATA __declspec(dllimport)
//2. declare new DbRef define
#undef  DBREF_DECLARE
#define DBREF_DECLARE(AcDbType)

#include "acm.h"
//////////////////////////////////////////////////////////////////////////
#include "acmdef.h"
#include "cauxent.h"
#include "stdMgr.h"
#include "symstd.h"
#include "symbol.h"
#include "SectionSym.h"
#include "dbobjptr.h"

Acad::ErrorStatus postToDb(AcDbEntity* ent, AcDbObjectId& objId);

//get section line standard
Adesk::Boolean
getSectionLineStandardId(AcDbObjectId& sectionStdId)
{
  //get current standard from standard manager.
  AcDbObjectId curStdId;
  acmStdMgr->getCurrent(curStdId);

  //get the section line standard from current standard
  const AcDbObjectPointer<AcmStandard> pStd(curStdId, AcDb::kForRead);
  if (Acad::eOk != pStd.openStatus()) 
    return false;

  if (Acad::eOk != pStd->getCurrentSymbolStd(ACRX_T("AmdtSectionSymStd"), sectionStdId))
  {
    acutPrintf(_T("Fail to get section line standard by %s standard!"), pStd->name());
    return false;
  }

  return true;
}

Adesk::Boolean
setSectionLineValues(AmdtSectionSym* pSectionLine)
{
  if (!pSectionLine)
    return Adesk::kFalse;

  //set properties for section line

  
  //get section line standard from standard manager.
  AcDbObjectId sectionStdId;
  if(getSectionLineStandardId(sectionStdId) != Adesk::kTrue)
    return Adesk::kFalse;

  //open section line standard object for writing.
  AcDbObjectPointer<AmdtSectionSymStd> pSectionStd(sectionStdId, AcDb::kForRead);
  if (Acad::eOk != pSectionStd.openStatus()) {
    acutPrintf(ACRX_T("section line standard can not be opened!\n"));
    return Adesk::kFalse;
  }
  
  
  //set label names of vertex in the section line
  if (pSectionStd->multipleNamesSupported())
  {
    CStringArray names;
    names.Add(_T("C"));
    names.Add(_T("D"));
    pSectionLine->setLabelNames(names);
  }
  else
    pSectionLine->setLabelName(_T("C"));

  //test label text;
  CString labelText;
  labelText = pSectionLine->labelText();
  if (!labelText.IsEmpty())
    acutPrintf(_T("label text of section line is %s"), labelText);

  pSectionLine->setLineVisibility(AmdtSectionSymStd::kBetweenPlanes);

  //set Arrow visibility
  pSectionLine->setShowArrows(Adesk::kTrue);

  //set label visibility
  pSectionLine->setShowAnnot(Adesk::kTrue);
  //set plane symbol visibility
  pSectionLine->setShowPlaneNames(Adesk::kTrue);

  return Adesk::kTrue;
}

void createSectionLine()
{
  //create section line object
  AmdtSectionSym *pSection = new AmdtSectionSym(); 
  assert(pSection);
  if (Acm::eOk != pSection->setSymbolDefaults()) {
    acutPrintf(_T("\nFail to set default for section line."));
    delete pSection;
    return;
  }

  //set section points.
  AcGePoint3dArray sectionPoints;
  sectionPoints.append(AcGePoint3d(12,13,0));
  sectionPoints.append(AcGePoint3d(14,10,0));
  sectionPoints.append(AcGePoint3d(13,8,0));
  sectionPoints.append(AcGePoint3d(16,6,0));

  //set the center of arc segment.
  AcGePoint3d arcPoint(13.5,9,0);
  AcGePoint3dArray arcPoints;
  arcPoints.append(arcPoint);

  //set segment type of every segment line.
  AcArray<Acm::SectionSymLineSegmentType> segTypes;
  segTypes.append(Acm::kLineSegment);
  segTypes.append(Acm::kArcSegmentCenter);
  segTypes.append(Acm::kLineSegment);
  segTypes.append(Acm::kLineSegment);

  //set segment points
  pSection->setSectionPoints(sectionPoints, arcPoints, segTypes);
  
  // set section side, its value is calculated by pick point and first vertex of section points.
  AcGePoint3d pickPoint(12,10,0);
  AcGeVector3d sideVec = pickPoint - sectionPoints.at(0);
  pSection->setSectionSide(sideVec);

  //set section line other properties.
  if (Adesk::kFalse == setSectionLineValues(pSection)) {
    acutPrintf(_T("Fail to set properties for section line"));
    delete pSection;
    return;
  }

  // Post to Database
  AcDbObjectId objId;
  if (postToDb(pSection, objId) != Acad::eOk) {
    acutPrintf(_T("Fail to add section line object to database"));
    delete pSection;
    return;
  }

  // create section view label
  // makeSectionEnt must be invoked after posting section line object to database.
  AcGePoint3d labelPoint(16,11,0);
  Acad::ErrorStatus es = pSection->makeSectionEnt(labelPoint, NULL);
  if (es != Acad::eOk){
    acutPrintf(_T("Fail to create section label"));
    delete pSection;
    return;
  }
  
  pSection->regen();

  pSection->close();
}

//set section line standard properties.
void editSectionLineStandard()
{
  //get section line standard from standard manager.
  AcDbObjectId sectionStdId;
  if(getSectionLineStandardId(sectionStdId) != Adesk::kTrue)
    return;

  //open section line standard object for writing.
  AcDbObjectPointer<AmdtSectionSymStd> pSectionStd(sectionStdId, AcDb::kForWrite);
  if (Acad::eOk != pSectionStd.openStatus()) {
    acutPrintf(ACRX_T("section line standard can not be opened!\n"));
    return;
  }
  
  //set section label properties
  pSectionStd->setShowAnnot(Adesk::kTrue);
  pSectionStd->setShowPlaneNames(Adesk::kTrue);
  pSectionStd->setMultipleNamesSupported(Adesk::kFalse);

  pSectionStd->setLabelPattern(_T("=SECTION <SECTION_LABEL_FIRST>-<SECTION_LABEL_LAST>"));
  pSectionStd->setLabelAbove(Adesk::kFalse);
  
  //set section line properties
  //set line weight
  pSectionStd->setLineWeightOver(AcDb::kLnWt050);

  // kContinuous, kNoLines, kBetweenPlanes
  AmdtSectionSymStd::LineVisibility lineV = pSectionStd->lineVisibility();
  if (lineV != AmdtSectionSymStd::kBetweenPlanes)
    pSectionStd->setLineVisibility(AmdtSectionSymStd::kBetweenPlanes);
  
  //get line color.
  int lineColor = pSectionStd->lineTrueColorOver().colorIndex();
  acutPrintf(_T("\nEnter new leader color <%d>: "), lineColor);
  int result = ads_getint(NULL, &lineColor);
  if (result == RTCAN || result == RTERROR)
    return;

  //set line color.
  AcCmColor color;
  color.setColorIndex(lineColor);
  pSectionStd->setLineTrueColorOver(color);
  
  //set arrow properties
  //set arrow visibility
  pSectionStd->setShowArrows(Adesk::kTrue);

  //set arrow type
  pSectionStd->setArrowType(Acm::kArrowClosed15);
  
  //edit arrow scale
  double arrowScale = pSectionStd->arwScale();
  acutPrintf(_T("\nEnter new arrow size <%.2f>: "), arrowScale);
  result = ads_getreal(NULL, &arrowScale);
  if (result == RTCAN || result == RTERROR)
    return;
  pSectionStd->setArwScale(arrowScale);

  //get arrow color.
  int arwColor = pSectionStd->leaderTrueColor().colorIndex();
  acutPrintf(_T("\nEnter new leader color <%d>: "), arwColor);
  result = ads_getint(NULL, &arwColor);
  if (result == RTCAN || result == RTERROR)
    return;

  //set arrow color.
  color.setColorIndex(arwColor);
  pSectionStd->setLeaderTrueColor(color);

  //set text properties
  //set text height
  double txtHeight = pSectionStd->textHeight();
  acutPrintf(_T("\nEnter new text height <%.2f>: "), txtHeight);
  result = ads_getreal(NULL, &txtHeight);
  if (result == RTCAN || result == RTERROR)
    return;
  pSectionStd->setTextHeight(txtHeight);
  //get text color
  int textColor = pSectionStd->textColor();
  acutPrintf(_T("\nEnter new text color <%d>: "), textColor);
  result = ads_getint(NULL, &textColor);
  if (result == RTCAN || result == RTERROR)
    return;

  //set text color
  pSectionStd->setTextColor(textColor);

  acutPrintf(_T("set SectionLine standard properties successful."));
}