ListPlnrQRtcList::~ListPlnrQRtcList() { clear(); };
static void curses_refresh(DisplayState *ds) { int chr, nextchr, keysym, keycode; if (invalidate) { clear(); refresh(); curses_calc_pad(); ds->surface->width = FONT_WIDTH * width; ds->surface->height = FONT_HEIGHT * height; vga_hw_invalidate(); invalidate = 0; } vga_hw_text_update(screen); nextchr = ERR; while (1) { /* while there are any pending key strokes to process */ if (nextchr == ERR) chr = getch(); else { chr = nextchr; nextchr = ERR; } if (chr == ERR) break; #ifdef KEY_RESIZE /* this shouldn't occur when we use a custom SIGWINCH handler */ if (chr == KEY_RESIZE) { clear(); refresh(); curses_calc_pad(); curses_update(ds, 0, 0, width, height); ds->surface->width = FONT_WIDTH * width; ds->surface->height = FONT_HEIGHT * height; continue; } #endif keycode = curses2keycode[chr]; if (keycode == -1) continue; /* alt key */ if (keycode == 1) { nextchr = getch(); if (nextchr != ERR) { keycode = curses2keycode[nextchr]; nextchr = ERR; if (keycode == -1) continue; keycode |= ALT; /* process keys reserved for qemu */ if (keycode >= QEMU_KEY_CONSOLE0 && keycode < QEMU_KEY_CONSOLE0 + 9) { erase(); wnoutrefresh(stdscr); console_select(keycode - QEMU_KEY_CONSOLE0); invalidate = 1; continue; } } } if (kbd_layout && !(keycode & GREY)) { keysym = keycode2keysym[keycode & KEY_MASK]; if (keysym == -1) keysym = chr; keycode &= ~KEY_MASK; keycode |= keysym2scancode(kbd_layout, keysym); } if (is_graphic_console()) { /* since terminals don't know about key press and release * events, we need to emit both for each key received */ if (keycode & SHIFT) kbd_put_keycode(SHIFT_CODE); if (keycode & CNTRL) kbd_put_keycode(CNTRL_CODE); if (keycode & ALT) kbd_put_keycode(ALT_CODE); if (keycode & GREY) kbd_put_keycode(GREY_CODE); kbd_put_keycode(keycode & KEY_MASK); if (keycode & GREY) kbd_put_keycode(GREY_CODE); kbd_put_keycode((keycode & KEY_MASK) | KEY_RELEASE); if (keycode & ALT) kbd_put_keycode(ALT_CODE | KEY_RELEASE); if (keycode & CNTRL) kbd_put_keycode(CNTRL_CODE | KEY_RELEASE); if (keycode & SHIFT) kbd_put_keycode(SHIFT_CODE | KEY_RELEASE); } else { keysym = curses2keysym[chr]; if (keysym == -1) keysym = chr; kbd_put_keysym(keysym); } } }
bool LibEventHttpClient::send(const std::string &url, const std::vector<std::string> &headers, int timeoutSeconds, bool async, const void *data /* = NULL */, int size /* = 0 */) { clear(); m_url = url; evhttp_request* request = evhttp_request_new(on_request_completed, this); // request headers bool keepalive = true; bool addHost = true; for (unsigned int i = 0; i < headers.size(); i++) { const std::string &header = headers[i]; size_t pos = header.find(':'); if (pos != std::string::npos && header[pos + 1] == ' ') { std::string name = header.substr(0, pos); if (strcasecmp(name.c_str(), "Connection") == 0) { keepalive = false; } else if (strcasecmp(name.c_str(), "Host") == 0) { addHost = false; } int ret = evhttp_add_header(request->output_headers, name.c_str(), header.c_str() + pos + 2); if (ret >= 0) { continue; } } Logger::Error("invalid request header: [%s]", header.c_str()); } if (keepalive) { evhttp_add_header(request->output_headers, "Connection", "keep-alive"); } if (addHost) { // REVIEW: libevent never sends a Host header (nor does it properly send // HTTP 400 for HTTP/1.1 requests without such a header), in blatent // violation of RFC2616; this should perhaps be fixed in the library // proper. For now, add it if it wasn't set by the caller. if (m_port == 80) { evhttp_add_header(request->output_headers, "Host", m_address.c_str()); } else { std::ostringstream ss; ss << m_address << ":" << m_port; evhttp_add_header(request->output_headers, "Host", ss.str().c_str()); } } // post data if (data && size) { evbuffer_add(request->output_buffer, data, size); } // url evhttp_cmd_type cmd = data ? EVHTTP_REQ_POST : EVHTTP_REQ_GET; // if we have a cached connection, we need to pump the event loop to clear // any "connection closed" events that may be sitting there patiently. if (m_conn) { event_base_loop(m_eventBase, EVLOOP_NONBLOCK); } // even if we had an m_conn immediately above, it may have been cleared out // by onConnectionClosed(). if (m_conn == nullptr) { m_conn = evhttp_connection_new(m_address.c_str(), m_port); evhttp_connection_set_closecb(m_conn, on_connection_closed, this); evhttp_connection_set_base(m_conn, m_eventBase); } int ret = evhttp_make_request(m_conn, request, cmd, url.c_str()); if (ret != 0) { Logger::Error("evhttp_make_request failed"); return false; } if (timeoutSeconds > 0) { struct timeval timeout; timeout.tv_sec = timeoutSeconds; timeout.tv_usec = 0; event_set(&m_eventTimeout, -1, 0, timer_callback, m_eventBase); event_base_set(m_eventBase, &m_eventTimeout); event_add(&m_eventTimeout, &timeout); } if (async) { m_thread = new AsyncFunc<LibEventHttpClient> (this, &LibEventHttpClient::sendImpl); m_thread->start(); } else { IOStatusHelper io("libevent_http", m_address.c_str(), m_port); sendImpl(); } return true; }
SharedMemory::Handle::~Handle() { clear(); }
Shard::~Shard() { clear(); // Delete all children. }
DecisionTreeThresholdNode::DecisionTreeThresholdNode() : DecisionTreeNode("DecisionTreeThresholdNode") { clear(); }
int main() { int type; int v = 0; /* to record variable a-z for = op */ double op2; char s[MAXOP]; while ((type = getop(s)) != EOF) { switch (type) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '$': /* * note: When a variable is reset using the = operator this could * lead to an unused value on the stack. This is why the * stack is cleared when a newline is encountered. */ if (isvar(type)) { push(getvar(type)); } else if (type == '$') { printf("error: no previously printed value\n"); } v = type; /* record for = op below */ break; case '=': if (v) { setvar(v, pop()); v = 0; } else { printf("error: no previous variable specified\n"); } break; case 'S': push(sin(pop())); break; case 'C': push(cos(pop())); break; case 'T': push(tan(pop())); break; case 'X': push(exp(pop())); break; case 'L': push(log10(pop())); break; case 'E': push(exp(pop())); break; case 'R': push(sqrt(pop())); break; case 'P': op2 = pop(); push(pow(pop(), op2)); break; case '!': clear(); break; case '@': swap(); break; case '#': duplicate(); break; case '&': printf("\t%.8g\n", setvar('$', top())); break; case NUMBER: push(atof(s)); break; case '+': push(pop() + pop()); break; case '*': push(pop() * pop()); break; case '-': op2 = pop(); push(pop() - op2); break; case '/': op2 = pop(); if (op2 != 0.0) push(pop() / op2); else printf("error: zero divisor for operator '/'\n"); break; case '%': op2 = pop(); if (op2 != 0.0) { /* In C the modulus operator only works on short, * integer, long, ... but not when the operands * are float or double. Thus we have to emulate a * modulus operation for operands of type double. * * note: <math.h> has the function fmod() for this * */ double d = pop(); if (d < op2) push(d); else if (d == op2) push(0.0); else { while ((d -= op2) > op2) ; if (d == op2) push(0.0); else push(d); } } else printf("error: zero divisor for operator '%%'\n"); break; /* case '|': /\* test command for ungets() *\/ */ /* ungets(" 23 4 + "); */ /* break; */ case '\n': printf("\t%.8g\n", setvar('$', pop())); clear(); /* clear the stack */ break; default: printf("error: unknown command %s\n", s); break; } } return 0; }
void SendCoinsDialog::accept() { clear(); }
Lex Scanner::get_lex(){ int d, j; CS = H; do { switch( CS ){ case H: if ( (c == ' ') || (c == '\n') || (c == '\r') || (c == '\t') ) gc(); else if (isalpha(c) || (c == '_')){ clear(); add(); gc(); CS = IDENT; } else if (isdigit(c)){ d = c - '0'; gc(); CS = NUMB; } else if (c == '/'){ gc(); CS = COMS; } else if ( (c == '<') || (c == '>') || (c == '=')){ clear(); add(); gc(); CS = ALE; } else if (c == EOF) return Lex(LEX_FIN,0,"EOF"); else if (c == '!'){ clear(); add(); gc(); CS = NEQ; } else if (c == '&'){ clear(); add(); gc(); CS = AND; } else if (c == '|'){ clear(); add(); gc(); CS = OR; } else if (c == '"'){ clear(); gc(); CS = STR; } else CS = DELIM; break; case IDENT: if (isalpha(c) || isdigit(c) || (c == '_')){ add(); gc(); } else if (j = look(buf,TW)) return Lex (words[j],j, buf); else{ j = TID.put(buf); return Lex (LEX_ID, j, buf); } break; case STR: if (c == '"'){ gc(); return Lex (LEX_STRING, 0, buf); } else if (c == '\\'){ gc(); CS = BSC; } else if (c == EOF) throw "String must be closed!"; else{ add(); gc(); } /*else throw "String can't contain \n!";*/ break; case BSC: if (c == 'n') throw "String can't contain '\\n'!"; else if (c == 't'){ char c1 = c; c = '\\'; add(); c = c1; add(); gc(); CS = STR; } else if (c == EOF) throw "Strinfg must be closed!"; else{ add(); gc(); CS = STR; } break; case NUMB: if (isdigit(c)){ d = c - '0' + d*10; gc(); } else return Lex (LEX_NUM, d,"Number"); break; case COMS: if (c == '*'){ gc(); CS = COM; } else{ return Lex(dlms[16], 16,"/"); } break; case COM: if (c == '*'){ gc(); CS = COME; } else if ( c == EOF ) throw "Comment must be closed!"; else gc(); break; case COME: if (c == '/'){ gc(); CS = H; } else if (c == EOF) throw "Comment must be closed!"; else { gc(); CS = COM; } break; case ALE: if (c == '='){ add(); gc(); j = look (buf, TD); return Lex (dlms[j], j, buf); } else { j = look (buf, TD); return Lex (dlms[j], j, buf); } break; case NEQ: if (c == '='){ add(); gc(); j = look (buf, TD); return Lex(LEX_NEQ, j,"!="); } else throw "Your symbol is Pyt!n. Repalce it. Oh, yes, try in next 6 years..."; break; case AND: if (c == '&'){ add(); gc(); j = look (buf, TD); return Lex (dlms[j], j,buf); } else throw '&'; break; case OR: if (c == '|'){ add(); gc(); j = look(buf, TD); return Lex (dlms[j], j,buf); } else throw '|'; break; case DELIM: clear(); add(); if (j = look(buf, TD)){ gc(); return Lex(dlms[j], j,buf); } else throw c; break; } } while(true); };
SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::SendCoinsDialog), clientModel(0), model(0), fNewRecipientAllowed(true), fFeeMinimized(true), platformStyle(platformStyle) { ui->setupUi(this); if (!platformStyle->getImagesOnButtons()) { ui->addButton->setIcon(QIcon()); ui->clearButton->setIcon(QIcon()); ui->sendButton->setIcon(QIcon()); } else { ui->addButton->setIcon(platformStyle->SingleColorIcon(":/icons/add")); ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); ui->sendButton->setIcon(platformStyle->SingleColorIcon(":/icons/send")); } GUIUtil::setupAddressWidget(ui->lineEditCoinControlChange, this); addEntry(); connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry())); connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); // Coin Control connect(ui->pushButtonCoinControl, SIGNAL(clicked()), this, SLOT(coinControlButtonClicked())); connect(ui->checkBoxCoinControlChange, SIGNAL(stateChanged(int)), this, SLOT(coinControlChangeChecked(int))); connect(ui->lineEditCoinControlChange, SIGNAL(textEdited(const QString &)), this, SLOT(coinControlChangeEdited(const QString &))); // Coin Control: clipboard actions QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this); QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this); QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this); QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this); QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this); QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardQuantity())); connect(clipboardAmountAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAmount())); connect(clipboardFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardFee())); connect(clipboardAfterFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAfterFee())); connect(clipboardBytesAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardBytes())); connect(clipboardPriorityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardPriority())); connect(clipboardLowOutputAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardLowOutput())); connect(clipboardChangeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardChange())); ui->labelCoinControlQuantity->addAction(clipboardQuantityAction); ui->labelCoinControlAmount->addAction(clipboardAmountAction); ui->labelCoinControlFee->addAction(clipboardFeeAction); ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction); ui->labelCoinControlBytes->addAction(clipboardBytesAction); ui->labelCoinControlPriority->addAction(clipboardPriorityAction); ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction); ui->labelCoinControlChange->addAction(clipboardChangeAction); // init transaction fee section QSettings settings; if (!settings.contains("fFeeSectionMinimized")) settings.setValue("fFeeSectionMinimized", true); if (!settings.contains("nFeeRadio") && settings.contains("nTransactionFee") && settings.value("nTransactionFee").toLongLong() > 0) // compatibility settings.setValue("nFeeRadio", 1); // custom if (!settings.contains("nFeeRadio")) settings.setValue("nFeeRadio", 0); // recommended if (!settings.contains("nCustomFeeRadio") && settings.contains("nTransactionFee") && settings.value("nTransactionFee").toLongLong() > 0) // compatibility settings.setValue("nCustomFeeRadio", 1); // total at least if (!settings.contains("nCustomFeeRadio")) settings.setValue("nCustomFeeRadio", 0); // per kilobyte if (!settings.contains("nSmartFeeSliderPosition")) settings.setValue("nSmartFeeSliderPosition", 0); if (!settings.contains("nTransactionFee")) settings.setValue("nTransactionFee", (qint64)DEFAULT_TRANSACTION_FEE); if (!settings.contains("fPayOnlyMinFee")) settings.setValue("fPayOnlyMinFee", false); // Dogecoin: Disable free transactions /* if (!settings.contains("fSendFreeTransactions")) settings.setValue("fSendFreeTransactions", false); */ ui->groupFee->setId(ui->radioSmartFee, 0); ui->groupFee->setId(ui->radioCustomFee, 1); ui->groupFee->button((int)std::max(0, std::min(1, settings.value("nFeeRadio").toInt())))->setChecked(true); ui->groupCustomFee->setId(ui->radioCustomPerKilobyte, 0); ui->groupCustomFee->setId(ui->radioCustomAtLeast, 1); ui->groupCustomFee->button((int)std::max(0, std::min(1, settings.value("nCustomFeeRadio").toInt())))->setChecked(true); ui->sliderSmartFee->setValue(settings.value("nSmartFeeSliderPosition").toInt()); ui->customFee->setValue(settings.value("nTransactionFee").toLongLong()); ui->checkBoxMinimumFee->setChecked(settings.value("fPayOnlyMinFee").toBool()); // Dogecoin: Disable free transactions // ui->checkBoxFreeTx->setChecked(settings.value("fSendFreeTransactions").toBool()); minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool()); }
void SendCoinsDialog::reject() { clear(); }
void ScriptUnitView::onRun() { clear(); m_data->run(); }
void CD3D11VertexDescriptor::removeAllAttribute() { CVertexDescriptor::removeAllAttribute(); clear(); }
NetworkResourcesData::~NetworkResourcesData() { clear(); }
LOCAL_CACHE_TEMPLATE LOCAL_CACHE_CLASS::~local_cache() { clear(); }
int main(int argc, char* argv[]){ /* Initialize pseudo random number generator */ srand(time(NULL)); /* Read command line arguments */ struct basic_options op; struct multi_options mop; if (get_options(argc, argv, &op, &mop) == 1) return 1; /* Setup signal handlers */ struct sigaction newhandler; /* new settings */ sigset_t blocked; /* set of blocked sigs */ newhandler.sa_flags = SA_RESTART; /* options */ sigemptyset(&blocked); /* clear all bits */ newhandler.sa_mask = blocked; /* store blockmask */ newhandler.sa_handler = on_timer; /* handler function */ if ( sigaction(SIGALRM, &newhandler, NULL) == -1 ) perror("sigaction"); /* prepare the terminal for the animation */ setlocale(LC_ALL, ""); initscr(); /* initialize the library and screen */ cbreak(); /* put terminal into non-blocking input mode */ noecho(); /* turn off echo */ start_color(); clear(); /* clear the screen */ curs_set(0); /* hide the cursor */ use_default_colors(); init_pair(0, COLOR_WHITE, COLOR_BLACK); init_pair(1, COLOR_WHITE, COLOR_BLACK); init_pair(2, COLOR_BLACK, COLOR_BLACK); init_pair(3, COLOR_RED, COLOR_BLACK); init_pair(4, COLOR_GREEN, COLOR_BLACK); init_pair(5, COLOR_BLUE, COLOR_BLACK); init_pair(6, COLOR_YELLOW, COLOR_BLACK); init_pair(7, COLOR_MAGENTA, COLOR_BLACK); init_pair(8, COLOR_CYAN, COLOR_BLACK); color_set(0, NULL); assume_default_colors(COLOR_WHITE, COLOR_BLACK); clear(); struct state st; struct ui ui; /* Initialize the parameters of the program */ attrset(A_BOLD | COLOR_PAIR(2)); mvaddstr(0,0,"Map is generated. Please wait."); refresh(); state_init(&st, &op, &mop); ui_init(&st, &ui); clear(); /* non-blocking input */ int fd_flags = fcntl(0, F_GETFL); fcntl(0, F_SETFL, (fd_flags|O_NONBLOCK)); /* Start the real time interval timer with delay interval size */ struct itimerval it; it.it_value.tv_sec = 0; it.it_value.tv_usec = 10000; it.it_interval.tv_sec = 0; it.it_interval.tv_usec = 10000; setitimer(ITIMER_REAL, &it, NULL); refresh(); input_ready = 0; time_to_redraw = 1; if (!mop.multiplayer_flag) { /* Run the game */ run(&st, &ui); } else { if (mop.server_flag) run_server(&st, mop.clients_num, mop.val_server_port); else run_client(&st, &ui, mop.val_server_addr, mop.val_server_port, mop.val_client_port); } /* Restore the teminal state */ echo(); curs_set(1); clear(); endwin(); if (!mop.multiplayer_flag || mop.server_flag) printf ("Random seed was %i\n", st.map_seed); free(mop.val_server_addr); free(mop.val_server_port); free(mop.val_client_port); return 0; }
DecisionTreeThresholdNode::~DecisionTreeThresholdNode(){ clear(); }
//GOODEND or BADEND void END(int end,int stgnum,node_t *trees,int auto_or_mamual,Agent_status *agent) { int total_points = agent->X; if (end == 0) { if (agent->X < 0) { total_points = 0; agent->X = 0; } if (agent->ENEMY_TOUCH_FLAG == 1) { total_points -= 50; } if (total_points < 0) { total_points = 0; } //BadEND if (agent->ON_OFF == 0){ mvprintw(LINES/2+1,COLS/2-10,"(>_<;) (>_< )"); mvprintw(LINES/2,COLS/2-4,"GAME OVER"); mvaddstr(LINES/2-3,COLS/2-10,"retry or quit [r/q] ?"); curs_set(0); Refresh(agent); mvprintw(LINES/2+1,COLS/2-12,"(>_<;)) (>_< ) "); mvprintw(LINES/2,COLS/2-4,"GAME OVER"); mvaddstr(LINES/2-3,COLS/2-10,"retry or quit [r/q] ?"); curs_set(0); Refresh(agent); mvprintw(LINES/2+1,COLS/2-14,"(>_<;)))) (T-T ) "); mvprintw(LINES/2,COLS/2-4,"GAME OVER"); mvaddstr(LINES/2-3,COLS/2-10,"retry or quit [r/q] ?"); curs_set(0); Refresh(agent); mvprintw(LINES/2+1,COLS/2-16,"(>_<;)))))sorry (T-T )"); mvprintw(LINES/2,COLS/2-4,"GAME OVER"); mvaddstr(LINES/2-3,COLS/2-10,"retry or quit [r/q] ?"); curs_set(0); mvprintw(LINES/4,COLS/2-20,"%d DISTANCE = TOTAL %d POINTS!!!",agent->X,total_points); Refresh(agent); } //agent->END_FLAG = 1; agent->TOTAL_POINTS = total_points; } else { //GoodEND if(agent->ON_OFF == 0) { clear(); mvprintw(LINES/2+1,COLS/2-8,"(*´<) (>'*)"); mvprintw(LINES/2,COLS/2-4,"GOOD END"); mvaddstr(LINES/2-3,COLS/2-10,"retry or quit [r/q] ?"); curs_set(0); Refresh(agent); clear(); mvprintw(LINES/2+1,COLS/2-7,"(*´<) (>'*)"); mvprintw(LINES/2,COLS/2-4,"GOOD END"); mvaddstr(LINES/2-3,COLS/2-10,"retry or quit [r/q] ?"); curs_set(0); Refresh(agent); clear(); mvprintw(LINES/2+1,COLS/2-6,"(*´<) (>'*)"); mvprintw(LINES/2,COLS/2-4,"GOOD END"); mvaddstr(LINES/2-3,COLS/2-10,"retry or quit [r/q] ?"); curs_set(0); Refresh(agent); clear(); mvprintw(LINES/2+1,COLS/2-5,"(*´з)(ε'*)chu!!"); mvprintw(LINES/2,COLS/2-4,"GOOD END"); mvaddstr(LINES/2-3,COLS/2-10,"retry or quit [r/q] ?"); curs_set(0); Refresh(agent); } total_points += agent->TIMES; mvprintw(LINES/4,COLS/2-30,"%d TIMES + %d DISTANCE = TOTAL %d POINTS!!!",agent->TIMES,agent->X,total_points); curs_set(0); Refresh(agent); }//Dead or Goal agent->END_FLAG = 1; agent->TOTAL_POINTS = total_points; }
DuokanTreeView::~DuokanTreeView() { clear(); }
QgsWfsCapabilities::Capabilities::Capabilities() { clear(); }
CMathDependencyGraph::~CMathDependencyGraph() { clear(); }
V3Graph::~V3Graph() { clear(); }
void QxtMediaKeys::deactivate() { clear(); }
IOWatch::IOWatch() { clear(); }
SocketSelector::SocketSelector() : m_impl(new SocketSelectorImpl) { clear(); }
CommandStack::~CommandStack() { clear(); }
void LibEventHttpClient::release() { clear(); m_busy = false; }
GlobalEvents::~GlobalEvents() { clear(); }
~MmapFile() { clear(); }
void PathFinder::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos) { // *** getting start/end poly logic *** float distToStartPoly, distToEndPoly; float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x}; float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x}; dtPolyRef startPoly = getPolyByLocation(startPoint, &distToStartPoly); dtPolyRef endPoly = getPolyByLocation(endPoint, &distToEndPoly); // we have a hole in our mesh // make shortcut path and mark it as NOPATH ( with flying exception ) // its up to caller how he will use this info if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); BuildShortcut(); m_type = (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->CanFly()) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; return; } // we may need a better number here bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f); if (farFromPoly) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); bool buildShotrcut = false; if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) { Creature* owner = (Creature*)m_sourceUnit; Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; if (m_sourceUnit->GetTerrain()->IsUnderWater(p.x, p.y, p.z)) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: underWater case\n"); if (owner->CanSwim()) buildShotrcut = true; } else { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: flying case\n"); if (owner->CanFly()) buildShotrcut = true; } } if (buildShotrcut) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return; } else { float closestPoint[VERTEX_SIZE]; // we may want to use closestPointOnPolyBoundary instead if (DT_SUCCESS == m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) { dtVcopy(endPoint, closestPoint); setActualEndPosition(Vector3(endPoint[2],endPoint[0],endPoint[1])); } m_type = PATHFIND_INCOMPLETE; } } // *** poly path generating logic *** // start and end are on same polygon // just need to move in straight line if (startPoly == endPoly) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPoly == endPoly)\n"); BuildShortcut(); m_pathPolyRefs[0] = startPoly; m_polyLength = 1; m_type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: path type %d\n", m_type); return; } // look for startPoly/endPoly in current path // TODO: we can merge it with getPathPolyByPosition() loop bool startPolyFound = false; bool endPolyFound = false; uint32 pathStartIndex, pathEndIndex; if (m_polyLength) { for (pathStartIndex = 0; pathStartIndex < m_polyLength; ++pathStartIndex) { // here to carch few bugs MANGOS_ASSERT(m_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); if (m_pathPolyRefs[pathStartIndex] == startPoly) { startPolyFound = true; break; } } for (pathEndIndex = m_polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) if (m_pathPolyRefs[pathEndIndex] == endPoly) { endPolyFound = true; break; } } if (startPolyFound && endPolyFound) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n"); // we moved along the path and the target did not move out of our old poly-path // our path is a simple subpath case, we have all the data we need // just "cut" it out m_polyLength = pathEndIndex - pathStartIndex + 1; memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, m_polyLength*sizeof(dtPolyRef)); } else if (startPolyFound && !endPolyFound) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n"); // we are moving on the old path but target moved out // so we have atleast part of poly-path ready m_polyLength -= pathStartIndex; // try to adjust the suffix of the path instead of recalculating entire length // at given interval the target cannot get too far from its last location // thus we have less poly to cover // sub-path of optimal path is optimal // take ~80% of the original length // TODO : play with the values here uint32 prefixPolyLength = uint32(m_polyLength*0.8f + 0.5f); memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, prefixPolyLength*sizeof(dtPolyRef)); dtPolyRef suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data float suffixEndPoint[VERTEX_SIZE]; if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) { // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that // try to recover by using prev polyref --prefixPolyLength; suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) { // suffixStartPoly is still invalid, error state BuildShortcut(); m_type = PATHFIND_NOPATH; return; } } // generate suffix uint32 suffixPolyLength = 0; dtStatus dtResult = m_navMeshQuery->findPath( suffixStartPoly, // start polygon endPoly, // end polygon suffixEndPoint, // start position endPoint, // end position &m_filter, // polygon search filter m_pathPolyRefs + prefixPolyLength - 1, // [out] path (int*)&suffixPolyLength, MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path if (!suffixPolyLength || dtResult != DT_SUCCESS) { // this is probably an error state, but we'll leave it // and hopefully recover on the next Update // we still need to copy our preffix sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); } DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength); // new path = prefix + suffix - overlap m_polyLength = prefixPolyLength + suffixPolyLength - 1; } else { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n"); // either we have no path at all -> first run // or something went really wrong -> we aren't moving along the path to the target // just generate new path // free and invalidate old path data clear(); dtStatus dtResult = m_navMeshQuery->findPath( startPoly, // start polygon endPoly, // end polygon startPoint, // start position endPoint, // end position &m_filter, // polygon search filter m_pathPolyRefs, // [out] path (int*)&m_polyLength, MAX_PATH_LENGTH); // max number of polygons in output path if (!m_polyLength || dtResult != DT_SUCCESS) { // only happens if we passed bad data to findPath(), or navmesh is messed up sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } } // by now we know what type of path we can get if (m_pathPolyRefs[m_polyLength - 1] == endPoly && !(m_type & PATHFIND_INCOMPLETE)) m_type = PATHFIND_NORMAL; else m_type = PATHFIND_INCOMPLETE; // generate the point-path out of our up-to-date poly-path BuildPointPath(startPoint, endPoint); }