void ArticulatedViewer::onGraphics3D(RenderDevice* rd, App* app, const shared_ptr<LightingEnvironment>& lighting, Array<shared_ptr<Surface> >& allSurfaces) { // app->gbuffer()->setSpecification(m_gbufferSpecification); app->gbuffer()->resize(app->framebuffer()->width(), app->framebuffer()->height()); app->gbuffer()->prepare(rd, app->activeCamera(), 0, -(float)app->previousSimTimeStep(), app->settings().depthGuardBandThickness, app->settings().colorGuardBandThickness); app->renderer()->render(rd, app->framebuffer(), app->depthPeelFramebuffer(), *lighting, app->gbuffer(), allSurfaces); Array<Point3> skeletonLines; m_model->getSkeletonLines(m_pose, m_offset, skeletonLines); rd->pushState(); { rd->setObjectToWorldMatrix(CFrame()); rd->setDepthTest(RenderDevice::DEPTH_ALWAYS_PASS); for (int i = 0; i < skeletonLines.size(); i += 2) { Draw::lineSegment(LineSegment::fromTwoPoints(skeletonLines[i], skeletonLines[i + 1]), rd, Color3::red()); } } rd->popState(); //Surface::renderWireframe(rd, posed3D); if (m_selectedMesh != NULL) { // Find the index array that matches the selected mesh and render it for (int p = 0; p < allSurfaces.size(); ++p) { const shared_ptr<UniversalSurface>& s = dynamic_pointer_cast<UniversalSurface>(allSurfaces[p]); if (s->gpuGeom()->index == m_selectedMesh->gpuIndexArray) { // These have the same index array, so they must be the same surface s->renderWireframeHomogeneous(rd, Array<shared_ptr<Surface> >(s), Color3::green(), false); break; } } } float x, y, z, yaw, pitch, roll; app->activeCamera()->frame().getXYZYPRDegrees(x,y,z,yaw, pitch, roll); screenPrintf("[Camera position: Translation(%f, %f, %f) Rotation(%f, %f, %f)]\n", x,y,z,yaw,pitch,roll); screenPrintf("[Shown scaled by %f and offset by (%f, %f, %f)]\n", m_scale, m_offset.x, m_offset.y, m_offset.z); screenPrintf("Model Faces: %d, Vertices: %d\n", m_numFaces, m_numVertices); if (m_selectedPart != NULL) { screenPrintf(" Selected Part `%s', Mesh `%s', Material `%s', cpuIndexArray[%d...%d]\n", m_selectedPart->name.c_str(), m_selectedMesh->name.c_str(), m_selectedMesh->material->name().c_str(), m_selectedTriangleIndex, m_selectedTriangleIndex + 2); screenPrintf(" Selected part->cframe = %s\n", m_selectedPart->cframe.toXYZYPRDegreesString().c_str()); } screenPrintf("Hierarchy:"); // Hierarchy (could do this with a PartCallback) for (int i = 0; i < m_model->rootArray().size(); ++i) { printHierarchy(m_model, m_model->rootArray()[i], ""); } }
static void printHierarchy (const shared_ptr<ArticulatedModel>& model, ArticulatedModel::Part* part, const G3D::String& indent) { screenPrintf("%s\"%s\")\n", indent.c_str(), part->name.c_str()); for (int i = 0; i < model->meshArray().size(); ++i) { if (model->meshArray()[i]->logicalPart == part) { screenPrintf("%s Mesh \"%s\"\n", indent.c_str(), model->meshArray()[i]->name.c_str()); } } for (int i = 0; i < part->childArray().size(); ++i) { printHierarchy(model, part->childArray()[i], indent + " "); } }
bool Robot::defineRobot(){ if(getType() == MOBILE){ name = "Mobile Robot"; Leaf *motor1 = new Leaf(0,0, 0,"motor0"); Leaf *motor2 = new Leaf(1,0, 0,"motor1"); Leaf *motor3 = new Leaf(2,0, 0,"motor2"); Leaf *sensor1 = new Leaf(100,0, 0,"sensor1"); Component *skeleton = new Component("Chasis"); skeleton->add(motor1); skeleton->add(motor2); skeleton->add(motor3); skeleton->add(sensor1); addComponent(skeleton); printHierarchy(); return true; }else if(getType() == HUMANOID){ name = "Humanoid Robot"; Leaf *motor1 = new Leaf(1,200, 0,"motor1"); Leaf *motor2 = new Leaf(2,800, 0,"motor2"); Leaf *motor3 = new Leaf(3,512, 0,"motor3"); Leaf *motor4 = new Leaf(4,512, 0,"motor4"); Leaf *motor5 = new Leaf(5,512, 0,"motor5"); Leaf *motor6 = new Leaf(6,512, 0,"motor6"); Leaf *motor7 = new Leaf(7,512, 0,"motor7"); Leaf *motor8 = new Leaf(8,512, 0,"motor8"); Leaf *motor9 = new Leaf(9,512, 0,"motor9"); Leaf *motor10 = new Leaf(10,512, 0,"moto10"); Leaf *motor11 = new Leaf(11,512, 0,"motor11"); Leaf *motor12 = new Leaf(12,512, 0,"motor12"); Leaf *motor13 = new Leaf(13,512, 0,"motor13"); Leaf *motor14 = new Leaf(14,512, 0,"motor14"); Leaf *motor15 = new Leaf(15,512, 0,"motor15"); Leaf *motor16 = new Leaf(16,512, 0,"motor16"); Leaf *motor17 = new Leaf(17,512, 0,"motor17"); Leaf *motor18 = new Leaf(18,512, 0,"motor18"); Leaf *sensor100 = new Leaf(100,512, 0,"sensor1"); Component *chest = new Component("Arm"); Component *right_arm = new Component("Right Arm"); Component *left_arm = new Component("Left Arm"); Component *torax = new Component("Torax"); Component *right_leg = new Component("Right Leg"); Component *left_leg = new Component("Left Leg"); Component *head = new Component("Head"); head->add(sensor100); chest->add(motor1); chest->add(motor2); right_arm->add(motor3); right_arm->add(motor5); left_arm->add(motor4); left_arm->add(motor6); torax->add(motor7); torax->add(motor8); right_leg->add(motor9); right_leg->add(motor11); right_leg->add(motor13); right_leg->add(motor15); right_leg->add(motor17); left_leg->add(motor10); left_leg->add(motor12); left_leg->add(motor14); left_leg->add(motor16); left_leg->add(motor18); addComponent(head); addComponent(chest); addComponent(right_arm); addComponent(left_arm); addComponent(torax); addComponent(right_leg); addComponent(left_leg); printHierarchy(); return true; } return false; }
int main(const int argc, const char * argv[]) { AppContext ctx; if (!appInit(argc, argv, "NTB Widgets Test", 1024, 768, &ctx)) { std::fprintf(stderr, "[APP_ERROR]: Failed to initialize sample app!\n"); return EXIT_FAILURE; } ntb::initialize(ctx.shellInterface, ctx.renderInterface); { bool done = false; ntb::GeometryBatch geoBatch; ntb::PODArray widgets{ sizeof(ntb::Widget *) }; ntb::GUI * gui = ntb::createGUI("Sample GUI"); // Basic blank widget: { auto w = new ntb::Widget{}; w->init(gui, nullptr, ntb::Rectangle{ 20, 20, 300, 300 }, true); widgets.pushBack(w); } // A set of buttons: { MyButtonEventListener buttonEventListener; const int buttonIconCount = static_cast<int>(ntb::ButtonWidget::Icon::Count); constexpr float btnScale = 1.6f; constexpr int btnSize = 50; constexpr int xStart = 350; constexpr int yStart = 20; int x = xStart; for (int i = 1; i < buttonIconCount; ++i) // Skip fist (Icon::None/0) { auto btn = new ntb::ButtonWidget{}; btn->init(gui, nullptr, ntb::Rectangle{ x, yStart, x + btnSize, yStart + btnSize }, true, ntb::ButtonWidget::Icon(i), &buttonEventListener); btn->setTextScaling(btnScale); btn->setState(true); x += btnSize + 20; // gap between each (20) widgets.pushBack(btn); } } // Title bar & Info bar widgets: { constexpr int btnOffsX = 20; constexpr int btnOffsY = 4; constexpr int btnSize = 40; constexpr int btnSpacing = 12; auto tb = new ntb::TitleBarWidget{}; tb->init(gui, nullptr, ntb::Rectangle{ 350, 120, 900, 170 }, true, "A title bar - drag me!", true, true, btnOffsX, btnOffsY, btnSize, btnSpacing); tb->setTextScaling(1.6f); // Title bar text tb->setButtonTextScaling(1.5f); // Button icon text widgets.pushBack(tb); auto ib = new ntb::InfoBarWidget{}; ib->init(gui, nullptr, ntb::Rectangle{ 350, 200, 900, 250 }, true, "Info bar"); ib->setTextScaling(1.6f); widgets.pushBack(ib); } // List widget: { auto l = new ntb::ListWidget{}; l->init(gui, nullptr, ntb::Rectangle{ 20, 350, 300, 500 }, true); l->setTextScaling(1.5f); l->allocEntries(4); l->addEntryText(0, "Hello"); l->addEntryText(1, "World"); l->addEntryText(2, "A longer string"); l->addEntryText(3, "And this one is even longer"); widgets.pushBack(l); } // Scrollbar widget: { auto sb = new ntb::ScrollBarWidget{}; sb->init(gui, nullptr, ntb::Rectangle{ 550, 300, 600, 600 }, true, 30); sb->updateLineScrollState(10, 5); widgets.pushBack(sb); } // Color Picker widget: { constexpr int colorPickerWidth = 360; constexpr int colorPickerHeight = 500; constexpr int xStart = 20; constexpr int yStart = 600; const ntb::Rectangle rect{ xStart, yStart, xStart + colorPickerWidth, yStart + colorPickerHeight }; auto cp = new ntb::ColorPickerWidget{}; cp->init(gui, nullptr, rect, true, 40, 28, 40, 25, 40); cp->setTextScaling(1.5f); cp->setButtonTextScaling(1.0f); widgets.pushBack(cp); } // 3D view widgets: { constexpr int view3dWidth = 450; constexpr int view3dHeight = 500; constexpr int xStart = 500; constexpr int yStart = 650; ntb::View3DWidget::ProjectionParameters projParams; projParams.fovYRadians = ntb::degToRad(60.0f); projParams.aspectRatio = 0.0f; // auto computed projParams.zNear = 0.5f; projParams.zFar = 100.0f; projParams.autoAdjustAspect = true; const int objCount = static_cast<int>(ntb::View3DWidget::ObjectType::Count); int x = xStart; for (int i = 1; i < objCount; ++i) { const ntb::Rectangle rect{ x, yStart, x + view3dWidth, yStart + view3dHeight }; auto v3d = new ntb::View3DWidget{}; v3d->init(gui, nullptr, rect, true, "3D View Widget", 40, 28, 10, projParams, ntb::View3DWidget::ObjectType(i)); v3d->setTextScaling(1.5f); v3d->setButtonTextScaling(1.0f); x += view3dWidth + 50; widgets.pushBack(v3d); } } // Var data display widgets inside a window/panel: { auto varWindow = new ntb::WindowWidget{}; varWindow->init(gui, nullptr, ntb::Rectangle{ 1000, 20, 1500, 600 }, true, false, "Variables Test", 40, 28, 40, 25); varWindow->setTextScaling(1.5f); varWindow->setButtonTextScaling(1.0f); constexpr int varStartX = 1100; constexpr int varStartY = 90; constexpr int varWidth = 300; constexpr int varHeight = 50; constexpr int varOffsY = 8; ntb::Rectangle rect; int y = varStartY; auto var0 = new ntb::VarDisplayWidget{}; rect.set(varStartX, y, varStartX + varWidth, y + varHeight); y += varHeight + varOffsY; var0->init(gui, nullptr, rect, true, varWindow, "Var 0"); var0->setTextScaling(1.5f); var0->setButtonTextScaling(1.5f); auto var1 = new ntb::VarDisplayWidget{}; rect.set(varStartX, y, varStartX + varWidth, y + varHeight); y += varHeight + varOffsY; var1->init(gui, var0, rect, true, varWindow, "Var 1"); var1->setTextScaling(1.5f); auto var2 = new ntb::VarDisplayWidget{}; rect.set(varStartX, y, varStartX + varWidth, y + varHeight); y += varHeight + varOffsY; var2->init(gui, var0, rect, true, varWindow, "Var 2"); var2->setTextScaling(1.5f); // Change sizes so child vars look nested under the parent int cX = varStartX + var0->getExpandCollapseButtonSize(); int cW = varWidth - var0->getExpandCollapseButtonSize(); auto var3 = new ntb::VarDisplayWidget{}; rect.set(cX, y, cX + cW, y + varHeight); y += varHeight + varOffsY; var3->init(gui, var0, rect, true, varWindow, "Var 3"); var3->setTextScaling(1.5f); var3->setButtonTextScaling(1.5f); auto var4 = new ntb::VarDisplayWidget{}; rect.set(cX, y, cX + cW, y + varHeight); y += varHeight + varOffsY; var4->init(gui, var3, rect, true, varWindow, "Var 4"); var4->setTextScaling(1.5f); cX += var0->getExpandCollapseButtonSize(); cW -= var0->getExpandCollapseButtonSize(); auto var5 = new ntb::VarDisplayWidget{}; rect.set(cX, y, cX + cW, y + varHeight); y += varHeight + varOffsY; var5->init(gui, var3, rect, true, varWindow, "Var 5"); var5->setTextScaling(1.5f); var5->setButtonTextScaling(1.5f); auto var6 = new ntb::VarDisplayWidget{}; rect.set(cX, y, cX + cW, y + varHeight); y += varHeight + varOffsY; var6->init(gui, var5, rect, true, varWindow, "Var 6"); var6->setTextScaling(1.5f); auto var7 = new ntb::VarDisplayWidget{}; rect.set(cX, y, cX + cW, y + varHeight); y += varHeight + varOffsY; var7->init(gui, var5, rect, true, varWindow, "Var 7"); var7->setTextScaling(1.5f); #if NEO_TWEAK_BAR_DEBUG varWindow->printHierarchy(); std::cout << "\n"; #endif // NEO_TWEAK_BAR_DEBUG // Only have to add the window, since each var widget is a child, directly or indirectly. widgets.pushBack(varWindow); } // Console/terminal window: { constexpr int maxLines = 1024; constexpr int bufferSize = 2048; auto con = new ntb::ConsoleWindowWidget{}; con->init(gui, nullptr, ntb::Rectangle{ 1550, 20, 2000, 420 }, true, true, "Console Window", 40, 28, 40, 25, maxLines, bufferSize); con->setTextScaling(1.3f); con->setButtonTextScaling(1.0f); ntb::SmallStr line; for (ntb::Int64 i = 0; i < 15; ++i) { line = "Test line "; line += ntb::SmallStr::fromNumber(i); con->pushLine(line.c_str(), line.getLength()); } con->onAdjustLayout(); // Update the scroll bar for lines out of view widgets.pushBack(con); } // To forward window input events to the widget list. ctx.setAppCallback(&ctx, &myAppEventCallback, &widgets); while (!done) { ctx.frameUpdate(&ctx, &done); geoBatch.beginDraw(); // Slider helper (not an actual widget, but used by some widgets): { static ntb::Float64 sliderPercent = 0.0; ntb::ValueSlider slider; slider.setRange(0, 100); slider.setCurrentValue(sliderPercent); slider.drawSelf(geoBatch, ntb::Rectangle{ 650, 350, 950, 400 }, ntb::packColor(255, 255, 255), ntb::packColor(255, 100, 0)); slider.drawSelf(geoBatch, ntb::Rectangle{ 650, 450, 950, 500 }, ntb::packColor(255, 255, 255), ntb::packColor(0, 200, 200)); sliderPercent += 0.2; if (sliderPercent > 100.0) { sliderPercent = 0.0; } } // Render our widgets: widgets.forEach<ntb::Widget *>( [](ntb::Widget * widget, ntb::GeometryBatch * batch) { widget->onDraw(*batch); return true; }, &geoBatch); geoBatch.endDraw(); ctx.framePresent(&ctx); } widgets.forEach<ntb::Widget *>( [](ntb::Widget * widget, void * /*unused*/) { delete widget; return true; }, nullptr); } ctx.shutdown(&ctx); ntb::shutdown(); // This will also free the GUI instance. }
/*=export_func optionSaveFile * * what: saves the option state to a file * * arg: tOptions*, pOpts, program options descriptor * * doc: * * This routine will save the state of option processing to a file. The name * of that file can be specified with the argument to the @code{--save-opts} * option, or by appending the @code{rcfile} attribute to the last * @code{homerc} attribute. If no @code{rcfile} attribute was specified, it * will default to @code{.@i{programname}rc}. If you wish to specify another * file, you should invoke the @code{SET_OPT_SAVE_OPTS( @i{filename} )} macro. * * The recommend usage is as follows: * @example * optionProcess(&progOptions, argc, argv); * if (i_want_a_non_standard_place_for_this) * SET_OPT_SAVE_OPTS("myfilename"); * optionSaveFile(&progOptions); * @end example * * err: * * If no @code{homerc} file was specified, this routine will silently return * and do nothing. If the output file cannot be created or updated, a message * will be printed to @code{stderr} and the routine will return. =*/ void optionSaveFile( tOptions* pOpts ) { tOptDesc* pOD; int ct; FILE* fp = openSaveFile(pOpts); if (fp == NULL) return; /* * FOR each of the defined options, ... */ ct = pOpts->presetOptCt; pOD = pOpts->pOptDesc; do { tOptDesc* p; /* * IF the option has not been defined * OR it does not take an initialization value * OR it is equivalenced to another option * THEN continue (ignore it) * * Equivalenced options get picked up when the equivalenced-to * option is processed. */ if (UNUSED_OPT( pOD )) continue; if ((pOD->fOptState & OPTST_DO_NOT_SAVE_MASK) != 0) continue; if ( (pOD->optEquivIndex != NO_EQUIVALENT) && (pOD->optEquivIndex != pOD->optIndex)) continue; /* * The option argument data are found at the equivalenced-to option, * but the actual option argument type comes from the original * option descriptor. Be careful! */ p = ((pOD->fOptState & OPTST_EQUIVALENCE) != 0) ? (pOpts->pOptDesc + pOD->optActualIndex) : pOD; switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { case OPARG_TYPE_NONE: printNoArgOpt(fp, p, pOD); break; case OPARG_TYPE_NUMERIC: printEntry( fp, p, (void*)(p->optArg.argInt)); break; case OPARG_TYPE_STRING: printStringArg(fp, p); break; case OPARG_TYPE_ENUMERATION: printEnumArg(fp, p); break; case OPARG_TYPE_MEMBERSHIP: printSetMemberArg(fp, p); break; case OPARG_TYPE_BOOLEAN: printEntry( fp, p, p->optArg.argBool ? "true" : "false" ); break; case OPARG_TYPE_HIERARCHY: printHierarchy(fp, p); break; case OPARG_TYPE_FILE: printFileArg(fp, p, pOpts); break; default: break; /* cannot handle - skip it */ } } while ( (pOD++), (--ct > 0)); fclose( fp ); }