void ossimS16ImageData::setValue(ossim_int32 x, ossim_int32 y, double color) { if(getBuf() != NULL && isWithin(x, y)) { //*** // Compute the offset into the buffer for (x,y). This should always // come out positive. //*** ossim_uint32 ux = static_cast<ossim_uint32>(x - m_origin.x); ossim_uint32 uy = static_cast<ossim_uint32>(y - m_origin.y); ossim_uint32 offset = uy * m_spatialExtents[0] + ux; for(ossim_uint32 band = 0; band < m_numberOfDataComponents; band++) { ossim_sint16* buf = getSshortBuf(band)+offset; *buf = (ossim_sint16)color; } } }
/** * Display the XP bar background and current progress. * On mouseover, display progress in text form. */ void MenuExperience::render(StatBlock *stats, Point mouse) { SDL_Rect src; SDL_Rect dest; int xp_bar_length; // don't display anything if max level // TODO: change this implementation if max level is configurable if (stats->level < 1 || stats->level >= 17) return; // lay down the background image first src.x = 0; src.y = 0; src.w = background_size.x; src.h = background_size.y; dest.x = hud_position.x + background_offset.x; dest.y = hud_position.y + background_offset.y; SDL_BlitSurface(background, &src, screen, &dest); // calculate the length of the xp bar // when at a new level, 0% progress src.x = 0; src.y = 0; int required = stats->xp_table[stats->level] - stats->xp_table[stats->level-1]; int current = stats->xp - stats->xp_table[stats->level-1]; xp_bar_length = (current * bar_size.x) / required; src.w = xp_bar_length; src.h = bar_size.y; dest.x = hud_position.x + bar_offset.x; dest.y = hud_position.y + bar_offset.y; // draw xp bar SDL_BlitSurface(bar, &src, screen, &dest); // if mouseover, draw text if (isWithin(hud_position, mouse)) { stringstream ss; ss.str(""); ss << text_label << stats->xp << "/" << stats->xp_table[stats->level]; font->render(ss.str(), hud_position.x + text_offset.x, hud_position.y + text_offset.y, text_justify, screen, FONT_WHITE); } }
void MenuManager::render() { for (unsigned int i=0; i<menus.size(); i++) { menus[i]->render(); } TooltipData tip_new; // Find tooltips depending on mouse position if (chr->visible && isWithin(chr->window_area,inpt->mouse)) { tip_new = chr->checkTooltip(); } if (vendor->visible && isWithin(vendor->window_area,inpt->mouse)) { tip_new = vendor->checkTooltip(inpt->mouse); } if (stash->visible && isWithin(stash->window_area,inpt->mouse)) { tip_new = stash->checkTooltip(inpt->mouse); } if (pow->visible && isWithin(pow->window_area,inpt->mouse)) { tip_new = pow->checkTooltip(inpt->mouse); } if (inv->visible && !dragging && isWithin(inv->window_area,inpt->mouse)) { tip_new = inv->checkTooltip(inpt->mouse); } if (isWithin(act->window_area,inpt->mouse)) { tip_new = act->checkTooltip(inpt->mouse); } if (!tip_new.isEmpty()) { // when we render a tooltip it buffers the rasterized text for performance. // If this new tooltip is the same as the existing one, reuse. if (!tip_new.compare(&tip_buf)) { tip_buf.clear(); tip_buf = tip_new; } tip->render(tip_buf, inpt->mouse, STYLE_FLOAT); } // draw icon under cursor if dragging if (dragging) { if (drag_src == DRAG_SRC_INVENTORY || drag_src == DRAG_SRC_VENDOR || drag_src == DRAG_SRC_STASH) items->renderIcon(drag_stack, inpt->mouse.x - ICON_SIZE/2, inpt->mouse.y - ICON_SIZE/2, ICON_SIZE); else if (drag_src == DRAG_SRC_POWERS || drag_src == DRAG_SRC_ACTIONBAR) renderIcon(powers->powers[drag_power].icon, inpt->mouse.x-ICON_SIZE/2, inpt->mouse.y-ICON_SIZE/2); } }
void WidgetButton::render() { SDL_Rect src; src.x = 0; src.w = pos.w; src.h = pos.h; // the "button" surface contains button variations. // choose which variation to display. if (!enabled) src.y = BUTTON_GFX_DISABLED * pos.h; else if (pressed) src.y = BUTTON_GFX_PRESSED * pos.h; else if (isWithin(pos, inp->mouse)) src.y = BUTTON_GFX_HOVER * pos.h; else src.y = BUTTON_GFX_NORMAL * pos.h; SDL_BlitSurface(buttons, &src, screen, &pos); wlabel.render(); }
Enemy* EnemyManager::enemyFocus(Point mouse, Point cam, bool alive_only) { Point p; SDL_Rect r; for(int i = 0; i < enemy_count; i++) { if(alive_only && (enemies[i]->stats.cur_state == ENEMY_DEAD || enemies[i]->stats.cur_state == ENEMY_CRITDEAD)) { continue; } p = map_to_screen(enemies[i]->stats.pos.x, enemies[i]->stats.pos.y, cam.x, cam.y); r.w = enemies[i]->getRender().src.w; r.h = enemies[i]->getRender().src.h; r.x = p.x - enemies[i]->getRender().offset.x; r.y = p.y - enemies[i]->getRender().offset.y; if (isWithin(r, mouse)) { Enemy *enemy = enemies[i]; return enemy; } } return NULL; }
void ossimU11ImageData::setValue(long x, long y, double color) { if(m_dataBuffer.size() > 0 && isWithin(x, y)) { //*** // Compute the offset into the buffer for (x,y). This should always // come out positive. //*** ossim_uint32 ux = static_cast<ossim_uint32>(x - m_origin.x); ossim_uint32 uy = static_cast<ossim_uint32>(y - m_origin.y); ossim_uint32 offset = uy * m_spatialExtents[0] + ux; for(ossim_uint32 band = 0; offset < m_dataBuffer.size() && // prevent buffer overrun band < m_numberOfDataComponents; band++) { ossim_uint16* buf = getUshortBuf(band)+offset; *buf = (ossim_uint16)color; } } }
/** * Show all tooltips for loot on the floor */ void LootManager::renderTooltips(FPoint cam) { Point dest; std::vector<Loot>::iterator it; for (it = loot.end(); it != loot.begin(); ) { --it; if (it->on_ground) { Point p = map_to_screen(it->pos.x, it->pos.y, cam.x, cam.y); dest.x = p.x; dest.y = p.y + TILE_H_HALF; // adjust dest.y so that the tooltip floats above the item dest.y -= tooltip_margin; // set hitbox for mouse hover Rect hover; hover.x = p.x - TILE_W_HALF; hover.y = p.y - TILE_H_HALF; hover.w = TILE_W; hover.h = TILE_H; if (LOOT_TOOLTIPS || inpt->pressing[ALT] || isWithin(hover, inpt->mouse)) { // create tooltip data if needed if (it->tip.isEmpty()) { if (!it->stack.empty()) { it->tip = items->getShortTooltip(it->stack); } } tip->render(it->tip, dest, STYLE_TOPLABEL); // only display one tooltip if we got it from hovering if (!LOOT_TOOLTIPS && !inpt->pressing[ALT]) break; } } } }
void WidgetInput::logic() { if (checkClick()) { inFocus = true; } // if clicking elsewhere unfocus the text box if (inp->pressing[MAIN1]) { if (!isWithin(pos, inp->mouse)) { inFocus = false; } } if (inFocus) { if (inp->inkeys != "") { // handle text input text += inp->inkeys; if (text.length() > max_characters) { text = text.substr(0, max_characters); } } // handle backspaces if (!inp->lock[DEL] && inp->pressing[DEL]) { inp->lock[DEL] = true; // remove utf-8 character int n = text.length()-1; while (n > 0 && ((text[n] & 0xc0) == 0x80) ) n--; text = text.substr(0, n); } // animate cursor // cursor visible one second, invisible the next cursor_frame++; if (cursor_frame == FRAMES_PER_SEC+FRAMES_PER_SEC) cursor_frame = 0; } }
// Get the list of currently loaded tiles that falls wiithin the area calculted from // the given paging distance void trpgPageManager::LodPageInfo::GetLoadedTileWithin(double pagingDistance, std::vector<trpgManagedTile*>& tileList) { trpg2iPoint aoi_size((int)(pagingDistance/cellSize.x) +1, (int)(pagingDistance/cellSize.y) +1); // Calculate the area that we must check, in parent cell coordinate trpg2iPoint sw, ne; sw.x = cell.x - aoi_size.x; sw.y = cell.y - aoi_size.y; ne.x = cell.x + aoi_size.x; ne.y = cell.y + aoi_size.y; sw.x = MAX(0,sw.x); sw.y = MAX(0,sw.y); ne.x = MIN(lodSize.x-1,ne.x); ne.y = MIN(lodSize.y-1,ne.y); tileList.clear(); for (unsigned i=0; i <current.size(); i++) { if (current[i] && isWithin(current[i],sw,ne)) tileList.push_back(current[i]); } }
void TabList::logic(bool allow_keyboard) { if (locked) return; if (NO_MOUSE || allow_keyboard) { if (scrolltype == VERTICAL || scrolltype == TWO_DIRECTIONS) { if (inpt->pressing[DOWN] && !inpt->lock[DOWN]) { inpt->lock[DOWN] = true; getNext(); } else if (inpt->pressing[UP] && !inpt->lock[UP]) { inpt->lock[UP] = true; getPrev(); } } if (scrolltype == HORIZONTAL || scrolltype == TWO_DIRECTIONS) { if (inpt->pressing[MV_LEFT] && !inpt->lock[MV_LEFT]) { inpt->lock[MV_LEFT] = true; getPrev(false); } else if (inpt->pressing[MV_RIGHT] && !inpt->lock[MV_RIGHT]) { inpt->lock[MV_RIGHT] = true; getNext(false); } } if (inpt->pressing[ACTIVATE] && !inpt->lock[ACTIVATE]) { inpt->lock[ACTIVATE] = true; deactivatePrevious(); //Deactivate previously activated item activate(); // Activate the currently infocus item } } // If mouse is clicked, defocus current tabindex item if (inpt->pressing[MAIN1] && !inpt->lock[MAIN1] && current_is_valid() && !isWithin(widgets[getCurrent()]->pos, inpt->mouse)) { defocus(); } }
int main(){ char c; int i; /* current digit */ int back=0; /* previous digit */ int pwback=1; /* number of ways till one digit back */ int pwbackback=0; /* number of ways till two digits back */ int pw=1; /* number of ways overall */ while(1){ c = getchar(); if (c == '0') break; while (c != '\n'){ i = c - '0'; if (i){ if (back == 0) pw = pwback; else if (isWithin(back,i)) pw = pwback + pwbackback; else pw = pwback; } // else account for 0s else{ pw = pwbackback; } back = i; pwbackback = pwback; pwback = pw; c = getchar(); } printf("%d\n", pw); back=0; pwback=1; pwbackback=0; pw=1; } return 0; }
bool AABox::expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const { // handle the trivial cases where the expanded box contains the start or end if (expandedContains(start, expansion) || expandedContains(end, expansion)) { return true; } // check each axis glm::vec3 expandedCorner = _corner - glm::vec3(expansion, expansion, expansion); glm::vec3 expandedSize = glm::vec3(_scale, _scale, _scale) + glm::vec3(expansion, expansion, expansion) * 2.0f; glm::vec3 direction = end - start; float axisDistance; return (findIntersection(start.x, direction.x, expandedCorner.x, expandedSize.x, axisDistance) && axisDistance >= 0.0f && axisDistance <= 1.0f && isWithin(start.y + axisDistance*direction.y, expandedCorner.y, expandedSize.y) && isWithin(start.z + axisDistance*direction.z, expandedCorner.z, expandedSize.z)) || (findIntersection(start.y, direction.y, expandedCorner.y, expandedSize.y, axisDistance) && axisDistance >= 0.0f && axisDistance <= 1.0f && isWithin(start.x + axisDistance*direction.x, expandedCorner.x, expandedSize.x) && isWithin(start.z + axisDistance*direction.z, expandedCorner.z, expandedSize.z)) || (findIntersection(start.z, direction.z, expandedCorner.z, expandedSize.z, axisDistance) && axisDistance >= 0.0f && axisDistance <= 1.0f && isWithin(start.y + axisDistance*direction.y, expandedCorner.y, expandedSize.y) && isWithin(start.x + axisDistance*direction.x, expandedCorner.x, expandedSize.x)); }
bool AABox::contains(const glm::vec3& point) const { return isWithin(point.x, _corner.x, _scale) && isWithin(point.y, _corner.y, _scale) && isWithin(point.z, _corner.z, _scale); }
/** * Some events have a hotspot (rectangle screen area) where the user can click * to trigger the event. * * The hero must be within range (INTERACT_RANGE) to activate an event. * * This function checks valid mouse clicks against all clickable events, and * executes */ void MapRenderer::checkHotspots() { if (NO_MOUSE) return; show_tooltip = false; std::vector<Event>::iterator it; // work backwards through events because events can be erased in the loop. // this prevents the iterator from becoming invalid. for (it = events.end(); it != events.begin(); ) { --it; for (int x=it->hotspot.x; x < it->hotspot.x + it->hotspot.w; ++x) { for (int y=it->hotspot.y; y < it->hotspot.y + it->hotspot.h; ++y) { bool matched = false; bool is_npc = false; Event_Component* npc = (*it).getComponent("npc_hotspot"); if (npc) { is_npc = true; Point p = map_to_screen(float(npc->x), float(npc->y), shakycam.x, shakycam.y); p = center_tile(p); Rect dest; dest.x = p.x - npc->z; dest.y = p.y - npc->a; dest.w = npc->b; dest.h = npc->c; if (isWithin(dest, inpt->mouse)) { matched = true; tip_pos.x = dest.x + dest.w/2; tip_pos.y = p.y - npc_tooltip_margin; } } else { for (unsigned index = 0; index <= index_objectlayer; ++index) { maprow *current_layer = layers[index]; Point p = map_to_screen(float(x), float(y), shakycam.x, shakycam.y); p = center_tile(p); if (const short current_tile = current_layer[x][y]) { // first check if mouse pointer is in rectangle of that tile: Rect dest; dest.x = p.x - tset.tiles[current_tile].offset.x; dest.y = p.y - tset.tiles[current_tile].offset.y; dest.w = tset.tiles[current_tile].tile->getClip().w; dest.h = tset.tiles[current_tile].tile->getClip().h; if (isWithin(dest, inpt->mouse)) { matched = true; tip_pos = map_to_screen(it->center.x, it->center.y, shakycam.x, shakycam.y); tip_pos.y -= TILE_H; } } } } if (matched) { // skip inactive events if (!EventManager::isActive(*it)) continue; // skip events without hotspots if ((*it).hotspot.h == 0) continue; // skip events on cooldown if ((*it).cooldown_ticks != 0) continue; // new tooltip? createTooltip((*it).getComponent("tooltip")); if ((((*it).reachable_from.w == 0 && (*it).reachable_from.h == 0) || isWithin((*it).reachable_from, floor(cam))) && calcDist(cam, (*it).center) < INTERACT_RANGE) { // only check events if the player is clicking // and allowed to click if (is_npc) { curs->setCursor(CURSOR_TALK); } else { curs->setCursor(CURSOR_INTERACT); } if (!inpt->pressing[MAIN1]) return; else if (inpt->lock[MAIN1]) return; inpt->lock[MAIN1] = true; if (EventManager::executeEvent(*it)) it = events.erase(it); } return; } else show_tooltip = false; } } } }
void WorkerThreadMain(void *param) { ThreadContext *context = (ThreadContext *)param; _int64 rangeStart, rangeLength; SAMReader *samReader = NULL; ReaderContext rcontext; rcontext.clipping = NoClipping; rcontext.genome = genome; rcontext.paired = false; rcontext.defaultReadGroup = ""; while (rangeSplitter->getNextRange(&rangeStart, &rangeLength)) { if (NULL == samReader) { samReader = SAMReader::create(DataSupplier::Default[true], inputFileName, rcontext, rangeStart, rangeLength); } else { ((ReadReader *)samReader)->reinit(rangeStart, rangeLength); } AlignmentResult alignmentResult; unsigned genomeLocation; Direction isRC; unsigned mapQ; unsigned flag; const char *cigar; unsigned nextFileToWrite = 0; Read read; LandauVishkinWithCigar lv; while (samReader->getNextRead(&read, &alignmentResult, &genomeLocation, &isRC, &mapQ, &flag, &cigar)) { if (mapQ < 0 || mapQ > MaxMAPQ) { fprintf(stderr,"Invalid MAPQ: %d\n",mapQ); exit(1); } if (0xffffffff == genomeLocation) { context->nUnaligned++; } else { if (flag & SAM_REVERSE_COMPLEMENT) { read.becomeRC(); } const Genome::Piece *piece = genome->getPieceAtLocation(genomeLocation); if (NULL == piece) { fprintf(stderr,"couldn't find genome piece for offset %u\n",genomeLocation); exit(1); } unsigned offsetA, offsetB; bool matched; const unsigned cigarBufLen = 1000; char cigarForAligned[cigarBufLen]; const char *alignedGenomeData = genome->getSubstring(genomeLocation, 1); int editDistance = lv.computeEditDistance(alignedGenomeData, read.getDataLength() + 20, read.getData(), read.getDataLength(), 30, cigarForAligned, cigarBufLen, false); if (editDistance == -1 || editDistance > MaxEditDistance) { editDistance = MaxEditDistance; } // // Parse the read ID. The format is ChrName_OffsetA_OffsetB_?:<more stuff>. This would be simple to parse, except that // ChrName can include "_". So, we parse it by looking for the first : and then working backward. // char idBuffer[10000]; // Hopefully big enough. I'm not worried about malicious input data here. memcpy(idBuffer,read.getId(),read.getIdLength()); idBuffer[read.getIdLength()] = 0; const char *firstColon = strchr(idBuffer,':'); bool badParse = true; size_t chrNameLen; const char *beginningOfSecondNumber; const char *beginningOfFirstNumber; int stage = 0; unsigned offsetOfCorrectChromosome; if (NULL != firstColon && firstColon - 3 > idBuffer && (*(firstColon-1) == '?' || isADigit(*(firstColon - 1)))) { // // We've parsed backwards to see that we have at least #: or ?: where '#' is a digit and ? is literal. If it's // a digit, then scan backwards through that number. // const char *underscoreBeforeFirstColon = firstColon - 2; while (underscoreBeforeFirstColon > idBuffer && isADigit(*underscoreBeforeFirstColon)) { underscoreBeforeFirstColon--; } if (*underscoreBeforeFirstColon == '_' && (isADigit(*(underscoreBeforeFirstColon - 1)) || *(underscoreBeforeFirstColon - 1) == '_')) { stage = 1; if (isADigit(*(underscoreBeforeFirstColon - 1))) { beginningOfSecondNumber = firstColon - 3; while (beginningOfSecondNumber > idBuffer && isADigit(*beginningOfSecondNumber)) { beginningOfSecondNumber--; } beginningOfSecondNumber++; // That loop actually moved us back one char before the beginning; } else { // // There's only one number, we have two consecutive underscores. // beginningOfSecondNumber = underscoreBeforeFirstColon; } if (beginningOfSecondNumber - 2 > idBuffer && *(beginningOfSecondNumber - 1) == '_' && isADigit(*(beginningOfSecondNumber - 2))) { stage = 2; beginningOfFirstNumber = beginningOfSecondNumber - 2; while (beginningOfFirstNumber > idBuffer && isADigit(*beginningOfFirstNumber)) { beginningOfFirstNumber--; } beginningOfFirstNumber++; // Again, we went one too far. offsetA = -1; offsetB = -1; if (*(beginningOfFirstNumber - 1) == '_' && 1 == sscanf(beginningOfFirstNumber,"%u",&offsetA) && ('_' == *beginningOfSecondNumber || 1 == sscanf(beginningOfSecondNumber,"%u", &offsetB))) { stage = 3; chrNameLen = (beginningOfFirstNumber - 1) - idBuffer; char correctChromosomeName[1000]; memcpy(correctChromosomeName, idBuffer, chrNameLen); correctChromosomeName[chrNameLen] = '\0'; if (!genome->getOffsetOfPiece(correctChromosomeName, &offsetOfCorrectChromosome)) { fprintf(stderr, "Couldn't parse chromosome name '%s' from read id\n", correctChromosomeName); } else { badParse = false; } } } } if (badParse) { fprintf(stderr,"Unable to parse read ID '%s', perhaps this isn't simulated data. piecelen = %d, pieceName = '%s', piece offset = %u, genome offset = %u\n", idBuffer, strlen(piece->name), piece->name, piece->beginningOffset, genomeLocation); exit(1); } bool match0 = false; bool match1 = false; if (-1 == offsetA || -1 == offsetB) { matched = false; } else if(strncmp(piece->name, idBuffer, __min(read.getIdLength(), chrNameLen))) { matched = false; } else { if (isWithin(offsetA, genomeLocation - piece->beginningOffset, 50)) { matched = true; match0 = true; } else if (isWithin(offsetB, genomeLocation - piece->beginningOffset, 50)) { matched = true; match1 = true; } else { matched = false; if (flag & SAM_FIRST_SEGMENT) { match0 = true; } else { match1 = true; } } } context->countOfReads[mapQ]++; context->countOfReadsByEditDistance[mapQ][editDistance]++; if (!matched) { context->countOfMisalignments[mapQ]++; context->countOfMisalignmentsByEditDistance[mapQ][editDistance]++; if (70 == mapQ || 69 == mapQ) { // // We don't know which offset is correct, because neither one matched. Just take the one with the lower edit distance. // unsigned correctLocationA = offsetOfCorrectChromosome + offsetA; unsigned correctLocationB = offsetOfCorrectChromosome + offsetB; unsigned correctLocation = 0; const char *correctData = NULL; const char *dataA = genome->getSubstring(correctLocationA, 1); const char *dataB = genome->getSubstring(correctLocationB, 1); int distanceA, distanceB; char cigarA[cigarBufLen]; char cigarB[cigarBufLen]; cigarA[0] = '*'; cigarA[1] = '\0'; cigarB[0] = '*'; cigarB[1] = '\0'; if (dataA == NULL) { distanceA = -1; } else { distanceA = lv.computeEditDistance(dataA, read.getDataLength() + 20, read.getData(), read.getDataLength(), 30, cigarA, cigarBufLen, false); } if (dataB == NULL) { distanceB = -1; } else { distanceB = lv.computeEditDistance(dataB, read.getDataLength() + 20, read.getData(), read.getDataLength(), 30, cigarB, cigarBufLen, false); } const char *correctGenomeData; char *cigarForCorrect; if (distanceA != -1 && distanceA <= distanceB || distanceB == -1) { correctGenomeData = dataA; correctLocation = correctLocationA; cigarForCorrect = cigarA; } else { correctGenomeData = dataB; correctLocation = correctLocationB; cigarForCorrect = cigarB; } printf("%s\t%d\t%s\t%u\t%d\t%s\t*\t*\t100\t%.*s\t%.*s\tAlignedGenomeLocation:%u\tCorrectGenomeLocation: %u\tCigarForCorrect: %s\tCorrectData: %.*s\tAlignedData: %.*s\n", idBuffer, flag, piece->name, genomeLocation - piece->beginningOffset, mapQ, cigarForAligned, read.getDataLength(), read.getData(), read.getDataLength(), read.getQuality(), genomeLocation, correctLocation, cigarForCorrect, read.getDataLength(), correctGenomeData, read.getDataLength(), alignedGenomeData); } } } } // if it was mapped } // for each read from the sam reader } if (0 == InterlockedAdd64AndReturnNewValue(&nRunningThreads, -1)) { SignalSingleWaiterObject(&allThreadsDone); } }
bool Shape::isWithin(int x, int y, int sx, int sy) { return isWithin( x, y, sx, sy, center_x, center_y); }
bool Shape::isWithin(int x, int y, int s) { return isWithin( x, y, s, center_x, center_y); }
/** * Sets and releases the "pressed" visual state of the ListBox * If press and release, activate (return true) */ bool WidgetListBox::checkClick(int x, int y) { Point mouse(x, y); refresh(); // check scroll wheel SDL_Rect scroll_area; scroll_area.x = rows[0].x; scroll_area.y = rows[0].y; scroll_area.w = rows[0].w; scroll_area.h = rows[0].h * list_height; if (isWithin(scroll_area,mouse)) { if (inpt->scroll_up) { scrollUp(); inpt->resetScroll(); } if (inpt->scroll_down) { scrollDown(); inpt->resetScroll(); } } else { inpt->resetScroll(); } // check ScrollBar clicks if (has_scroll_bar) { switch (scrollbar->checkClick(mouse.x,mouse.y)) { case 1: scrollUp(); break; case 2: scrollDown(); break; case 3: cursor = scrollbar->getValue(); refresh(); break; default: break; } } // main ListBox already in use, new click not allowed if (inpt->lock[MAIN1]) return false; // main click released, so the ListBox state goes back to unpressed if (pressed && !inpt->lock[MAIN1] && can_select) { pressed = false; for(int i=0; i<list_height; i++) { if (i<list_amount) { if (isWithin(rows[i], mouse) && values[i+cursor] != "") { // deselect other options if multi-select is disabled if (!multi_select) { for (int j=0; j<list_amount; j++) { if (j!=i+cursor) selected[j] = false; } } // activate upon release if (selected[i+cursor]) { if (can_deselect) selected[i+cursor] = false; } else { selected[i+cursor] = true; } refresh(); return true; } } } } pressed = false; // detect new click if (inpt->pressing[MAIN1]) { for (int i=0; i<list_height;i++) { if (isWithin(rows[i], mouse)) { inpt->lock[MAIN1] = true; pressed = true; } } } return false; }
bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const { // handle the trivial case where the box contains the origin if (contains(origin)) { // We still want to calculate the distance from the origin to the inside out plane float axisDistance; if ((findInsideOutIntersection(origin.x, direction.x, _corner.x, _scale, axisDistance) && axisDistance >= 0 && isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { distance = axisDistance; face = direction.x > 0 ? MAX_X_FACE : MIN_X_FACE; return true; } if ((findInsideOutIntersection(origin.y, direction.y, _corner.y, _scale, axisDistance) && axisDistance >= 0 && isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale) && isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { distance = axisDistance; face = direction.y > 0 ? MAX_Y_FACE : MIN_Y_FACE; return true; } if ((findInsideOutIntersection(origin.z, direction.z, _corner.z, _scale, axisDistance) && axisDistance >= 0 && isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale))) { distance = axisDistance; face = direction.z > 0 ? MAX_Z_FACE : MIN_Z_FACE; return true; } // This case is unexpected, but mimics the previous behavior for inside out intersections distance = 0; return true; } // check each axis float axisDistance; if ((findIntersection(origin.x, direction.x, _corner.x, _scale, axisDistance) && axisDistance >= 0 && isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { distance = axisDistance; face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE; return true; } if ((findIntersection(origin.y, direction.y, _corner.y, _scale, axisDistance) && axisDistance >= 0 && isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale) && isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { distance = axisDistance; face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE; return true; } if ((findIntersection(origin.z, direction.z, _corner.z, _scale, axisDistance) && axisDistance >= 0 && isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale))) { distance = axisDistance; face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE; return true; } return false; }
/** * Show mouseover descriptions of disciplines and powers */ TooltipData MenuPowers::checkTooltip(Point mouse) { TooltipData tip; int offset_x = (VIEW_W - 320); int offset_y = (VIEW_H - 416)/2; if (mouse.y >= offset_y+32 && mouse.y <= offset_y+80) { if (mouse.x >= offset_x+48 && mouse.x <= offset_x+80) { tip.lines[tip.num_lines++] = "Physical + Offense grants melee and ranged attacks"; return tip; } if (mouse.x >= offset_x+112 && mouse.x <= offset_x+144) { tip.lines[tip.num_lines++] = "Physical + Defense grants melee protection"; return tip; } if (mouse.x >= offset_x+176 && mouse.x <= offset_x+208) { tip.lines[tip.num_lines++] = "Mental + Offense grants elemental spell attacks"; return tip; } if (mouse.x >= offset_x+240 && mouse.x <= offset_x+272) { tip.lines[tip.num_lines++] = "Mental + Defense grants healing and magical protection"; return tip; } } else { for (int i=0; i<20; i++) { if (isWithin(slots[i], mouse)) { tip.lines[tip.num_lines++] = powers->powers[i].name; tip.lines[tip.num_lines++] = powers->powers[i].description; if (powers->powers[i].requires_physical_weapon) tip.lines[tip.num_lines++] = "Requires a physical weapon"; else if (powers->powers[i].requires_mental_weapon) tip.lines[tip.num_lines++] = "Requires a mental weapon"; else if (powers->powers[i].requires_offense_weapon) tip.lines[tip.num_lines++] = "Requires an offense weapon"; // add requirement int required_val = (i / 4) * 2 + 1; int required_stat = i % 4; stringstream ss; ss.str(""); ss << "Requires "; if (required_val > 1) { if (required_stat == 0) ss << "Physical Offense "; else if (required_stat == 1) ss << "Physical Defense "; else if (required_stat == 2) ss << "Mental Offense "; else ss << "Mental Defense "; ss << required_val; if (!requirementsMet(i)) tip.colors[tip.num_lines] = FONT_RED; tip.lines[tip.num_lines++] = ss.str(); } // add mana cost if (powers->powers[i].requires_mp > 0) { int mp_cost = powers->powers[i].requires_mp; stringstream ss; ss.str(""); ss << "Costs "; ss << mp_cost; ss << " MP"; tip.lines[tip.num_lines++] = ss.str(); } return tip; } } } return tip; }
void HazardManager::logic() { // remove all hazards with lifespan 0. Most hazards still display their last frame. for (size_t i=h.size(); i>0; i--) { if (h[i-1]->lifespan == 0) expire(i-1); } checkNewHazards(); // handle single-frame transforms for (size_t i=h.size(); i>0; i--) { h[i-1]->logic(); // remove all hazards that need to die immediately (e.g. exit the map) if (h[i-1]->remove_now) { expire(i-1); continue; } // if a moving hazard hits a wall, check for an after-effect if (h[i-1]->hit_wall && h[i-1]->wall_power > 0) { powers->activate(h[i-1]->wall_power, h[i-1]->src_stats, h[i-1]->pos); if (powers->powers[h[i-1]->wall_power].directional) powers->hazards.back()->animationKind = h[i-1]->animationKind; } } bool hit; // handle collisions for (size_t i=0; i<h.size(); i++) { if (h[i]->isDangerousNow()) { // process hazards that can hurt enemies if (h[i]->source_type != SOURCE_TYPE_ENEMY) { //hero or neutral sources for (unsigned int eindex = 0; eindex < enemies->enemies.size(); eindex++) { // only check living enemies if (enemies->enemies[eindex]->stats.hp > 0 && h[i]->active && (enemies->enemies[eindex]->stats.hero_ally == h[i]->target_party)) { if (isWithin(h[i]->pos, h[i]->radius, enemies->enemies[eindex]->stats.pos)) { if (!h[i]->hasEntity(enemies->enemies[eindex])) { h[i]->addEntity(enemies->enemies[eindex]); if (!h[i]->beacon) last_enemy = enemies->enemies[eindex]; // hit! hit = enemies->enemies[eindex]->takeHit(*h[i]); hitEntity(i, hit); } } } } } // process hazards that can hurt the hero if (h[i]->source_type != SOURCE_TYPE_HERO && h[i]->source_type != SOURCE_TYPE_ALLY) { //enemy or neutral sources if (pc->stats.hp > 0 && h[i]->active) { if (isWithin(h[i]->pos, h[i]->radius, pc->stats.pos)) { if (!h[i]->hasEntity(pc)) { h[i]->addEntity(pc); // hit! hit = pc->takeHit(*h[i]); hitEntity(i, hit); } } } //now process allies for (unsigned int eindex = 0; eindex < enemies->enemies.size(); eindex++) { // only check living allies if (enemies->enemies[eindex]->stats.hp > 0 && h[i]->active && enemies->enemies[eindex]->stats.hero_ally) { if (isWithin(h[i]->pos, h[i]->radius, enemies->enemies[eindex]->stats.pos)) { if (!h[i]->hasEntity(enemies->enemies[eindex])) { h[i]->addEntity(enemies->enemies[eindex]); // hit! hit = enemies->enemies[eindex]->takeHit(*h[i]); hitEntity(i, hit); } } } } } } } }
bool MBR::isWithin(PointAccessor * point) { return isWithin(&(*point)[0]); }
void MenuManager::logic() { bool clicking_character = false; bool clicking_inventory = false; bool clicking_powers = false; bool clicking_log = false; ItemStack stack; hp->update(stats->hp,stats->maxhp,inpt->mouse,""); mp->update(stats->mp,stats->maxmp,inpt->mouse,""); xp->update((stats->xp - stats->xp_table[stats->level-1]),(stats->xp_table[stats->level] - stats->xp_table[stats->level-1]),inpt->mouse,msg->get("XP: %d/%d", stats->xp, stats->xp_table[stats->level])); effects->update(stats); hudlog->logic(); enemy->logic(); chr->logic(); inv->logic(); vendor->logic(); pow->logic(); log->logic(); talker->logic(); stash->logic(); if (chr->checkUpgrade() || stats->level_up) { // apply equipment and max hp/mp inv->applyEquipment(inv->inventory[EQUIPMENT].storage); stats->hp = stats->maxhp; stats->mp = stats->maxmp; stats->level_up = false; } // only allow the vendor window to be open if the inventory is open if (vendor->visible && !(inv->visible)) { snd->play(vendor->sfx_close); closeLeft(); if (vendor->talker_visible && !(inv->visible)) closeRight(); } if (!inpt->pressing[INVENTORY] && !inpt->pressing[POWERS] && !inpt->pressing[CHARACTER] && !inpt->pressing[LOG]) key_lock = false; // handle npc action menu if (npc->visible) { npc->logic(); } // check if mouse-clicking a menu button act->checkMenu(inpt->mouse, clicking_character, clicking_inventory, clicking_powers, clicking_log); if (exit->visible) { exit->logic(); if (exit->isExitRequested()) { done = true; } } // exit menu toggle if ((!key_lock && !dragging) && !(stats->corpse && stats->permadeath)) { if (inpt->pressing[CANCEL] && !inpt->lock[CANCEL]) { inpt->lock[CANCEL] = true; key_lock = true; if (menus_open) { closeAll(); } else { exit->visible = !exit->visible; } } } // inventory menu toggle if ((inpt->pressing[INVENTORY] && !key_lock && !dragging) || clicking_inventory) { key_lock = true; if (inv->visible) { snd->play(inv->sfx_close); closeRight(); } else { closeRight(); act->requires_attention[MENU_INVENTORY] = false; inv->visible = true; snd->play(inv->sfx_open); } } // powers menu toggle if (((inpt->pressing[POWERS] && !key_lock && !dragging) || clicking_powers) && stats->humanoid) { key_lock = true; if (pow->visible) { snd->play(pow->sfx_close); closeRight(); } else { closeRight(); act->requires_attention[MENU_POWERS] = false; pow->visible = true; snd->play(pow->sfx_open); } } act->requires_attention[MENU_POWERS] = pow->getUnspent() > 0; // character menu toggleggle if (((inpt->pressing[CHARACTER] && !key_lock && !dragging) || clicking_character)) { key_lock = true; if (chr->visible) { snd->play(chr->sfx_close); closeLeft(); } else { closeLeft(); act->requires_attention[MENU_CHARACTER] = false; chr->visible = true; snd->play(chr->sfx_open); // Make sure the stat list isn't scrolled when we open the character menu inpt->resetScroll(); } } act->requires_attention[MENU_CHARACTER] = chr->getUnspent() > 0; // log menu toggle if ((inpt->pressing[LOG] && !key_lock && !dragging) || clicking_log) { key_lock = true; if (log->visible) { snd->play(log->sfx_close); closeLeft(); } else { closeLeft(); act->requires_attention[MENU_LOG] = false; log->visible = true; snd->play(log->sfx_open); // Make sure the log isn't scrolled when we open the log menu inpt->resetScroll(); } } if (MENUS_PAUSE) { pause = (inv->visible || pow->visible || chr->visible || log->visible || vendor->visible || talker->visible || npc->visible); } menus_open = (inv->visible || pow->visible || chr->visible || log->visible || vendor->visible || talker->visible || npc->visible); if (ENABLE_JOYSTICK && (menus_open || exit->visible)) inpt->enableMouseEmulation(); else inpt->disableMouseEmulation(); if (stats->alive) { // handle right-click if (!dragging && inpt->pressing[MAIN2] && !inpt->lock[MAIN2]) { // exit menu if (exit->visible && isWithin(exit->window_area, inpt->mouse)) { inpt->lock[MAIN2] = true; } // activate inventory item else if (inv->visible && isWithin(inv->window_area, inpt->mouse)) { inpt->lock[MAIN2] = true; if (isWithin(inv->carried_area, inpt->mouse)) { inv->activate(inpt); } } } // handle left-click if (!dragging && inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) { // exit menu if (exit->visible && isWithin(exit->window_area, inpt->mouse)) { inpt->lock[MAIN1] = true; } if (chr->visible && isWithin(chr->window_area, inpt->mouse)) { inpt->lock[MAIN1] = true; } if (vendor->visible && isWithin(vendor->window_area,inpt->mouse)) { inpt->lock[MAIN1] = true; vendor->tabsLogic(); if (inpt->pressing[CTRL]) { // buy item from a vendor stack = vendor->click(inpt); if (stack.item > 0) { if (!inv->buy(stack,vendor->getTab())) { log->add(msg->get("Not enough money."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Not enough money.")); vendor->itemReturn( stack); } else { if (inv->full(stack.item)) { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); drop_stack = stack; } else { inv->add(stack); } } } } else { // start dragging a vendor item drag_stack = vendor->click(inpt); if (drag_stack.item > 0) { dragging = true; drag_src = DRAG_SRC_VENDOR; } } } if (stash->visible && isWithin(stash->window_area,inpt->mouse)) { inpt->lock[MAIN1] = true; if (inpt->pressing[CTRL]) { // take an item from the stash stack = stash->click(inpt); if (stack.item > 0) { if (inv->full(stack.item)) { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); drop_stack = stack; } else { inv->add(stack); } stash->updated = true; } } else { // start dragging a stash item drag_stack = stash->click(inpt); if (drag_stack.item > 0) { dragging = true; drag_src = DRAG_SRC_STASH; } } } if (log->visible && isWithin(log->window_area,inpt->mouse)) { inpt->lock[MAIN1] = true; } // pick up an inventory item if (inv->visible && isWithin(inv->window_area,inpt->mouse)) { if (inpt->pressing[CTRL]) { inpt->lock[MAIN1] = true; stack = inv->click(inpt); if (stack.item > 0) { if (stash->visible) { if (inv->stashAdd(stack) && !stash->full(stack.item)) { stash->add(stack); stash->updated = true; } else { inv->itemReturn(stack); } } else { // The vendor could have a limited amount of money in the future. It will be tested here. if ((SELL_WITHOUT_VENDOR || vendor->visible) && inv->sell(stack)) { vendor->setTab(VENDOR_SELL); vendor->add(stack); } else { inv->itemReturn(stack); } } } } else { inpt->lock[MAIN1] = true; drag_stack = inv->click(inpt); if (drag_stack.item > 0) { dragging = true; drag_src = DRAG_SRC_INVENTORY; } } } // pick up a power if (pow->visible && isWithin(pow->window_area,inpt->mouse)) { inpt->lock[MAIN1] = true; // check for unlock first if (!pow->unlockClick(inpt->mouse)) { // otherwise, check for dragging drag_power = pow->click(inpt->mouse); if (drag_power > 0) { dragging = true; drag_src = DRAG_SRC_POWERS; } } } // action bar if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse) || isWithin(act->menuArea, inpt->mouse)) { inpt->lock[MAIN1] = true; // ctrl-click action bar to clear that slot if (inpt->pressing[CTRL]) { act->remove(inpt->mouse); } // allow drag-to-rearrange action bar else if (!isWithin(act->menuArea, inpt->mouse)) { drag_power = act->checkDrag(inpt->mouse); if (drag_power > 0) { dragging = true; drag_src = DRAG_SRC_ACTIONBAR; } } // else, clicking action bar to use a power? // this check is done by GameEngine when calling Avatar::logic() } } // handle dropping if (dragging && !inpt->pressing[MAIN1]) { // putting a power on the Action Bar if (drag_src == DRAG_SRC_POWERS) { if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse)) { act->drop(inpt->mouse, drag_power, 0); } } // rearranging the action bar else if (drag_src == DRAG_SRC_ACTIONBAR) { if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse)) { act->drop(inpt->mouse, drag_power, 1); // for locked slots forbid power dropping } else if (act->locked[act->drag_prev_slot]) { act->hotkeys[act->drag_prev_slot] = drag_power; } } // rearranging inventory or dropping items else if (drag_src == DRAG_SRC_INVENTORY) { if (inv->visible && isWithin(inv->window_area, inpt->mouse)) { inv->drop(inpt->mouse, drag_stack); drag_stack.item = 0; } else if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse)) { // The action bar is not storage! inv->itemReturn(drag_stack); // put an item with a power on the action bar if (items->items[drag_stack.item].power != 0) { act->drop(inpt->mouse, items->items[drag_stack.item].power, false); } } else if (vendor->visible && isWithin(vendor->slots_area, inpt->mouse)) { if (inv->sell( drag_stack)) { vendor->setTab(VENDOR_SELL); vendor->add( drag_stack); } else { inv->itemReturn(drag_stack); } drag_stack.item = 0; } else if (stash->visible && isWithin(stash->slots_area, inpt->mouse)) { if (inv->stashAdd( drag_stack) && !stash->full(drag_stack.item)) { stash->drop(inpt->mouse, drag_stack); stash->updated = true; } else { inv->itemReturn(drag_stack); } drag_stack.item = 0; } else { // if dragging and the source was inventory, drop item to the floor // quest items cannot be dropped if (items->items[drag_stack.item].type != "quest") { drop_stack = drag_stack; drag_stack.item = 0; drag_stack.quantity = 0; inv->clearHighlight(); } else { inv->itemReturn(drag_stack); } } } else if (drag_src == DRAG_SRC_VENDOR) { // dropping an item from vendor (we only allow to drop into the carried area) if (inv->visible && isWithin( inv->carried_area, inpt->mouse)) { if (!inv->buy(drag_stack,vendor->getTab())) { log->add(msg->get("Not enough money."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Not enough money.")); vendor->itemReturn( drag_stack); } else { if (inv->full(drag_stack.item)) { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); drop_stack = drag_stack; } else { inv->drop(inpt->mouse,drag_stack); } } drag_stack.item = 0; drag_stack.quantity = 0; } else { vendor->itemReturn(drag_stack); } } else if (drag_src == DRAG_SRC_STASH) { // dropping an item from stash (we only allow to drop into the carried area) if (inv->visible && isWithin( inv->carried_area, inpt->mouse)) { if (inv->full(drag_stack.item)) { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); // quest items cannot be dropped if (items->items[drag_stack.item].type != "quest") { drop_stack = drag_stack; } else { stash->itemReturn(drag_stack); } } else { inv->drop(inpt->mouse,drag_stack); } stash->updated = true; drag_stack.item = 0; drag_stack.quantity = 0; } else if (stash->visible && isWithin(stash->slots_area, inpt->mouse)) { stash->drop(inpt->mouse,drag_stack); } else { stash->itemReturn( drag_stack); } } dragging = false; } } else { if (dragging) { if (drag_src == DRAG_SRC_VENDOR) vendor->itemReturn(drag_stack); else if (drag_src == DRAG_SRC_STASH) stash->itemReturn(drag_stack); else if (drag_src == DRAG_SRC_INVENTORY) inv->itemReturn(drag_stack); else if (drag_src == DRAG_SRC_ACTIONBAR) act->actionReturn(drag_power); drag_src = -1; dragging = false; } } // handle equipment changes affecting hero stats if (inv->changed_equipment || inv->changed_artifact) { inv->applyEquipment(inv->inventory[EQUIPMENT].storage); inv->changed_artifact = false; // the equipment flag is reset after the new sprites are loaded } // for action-bar powers that represent items, lookup the current item count for (int i=0; i<12; i++) { act->slot_enabled[i] = true; act->slot_item_count[i] = -1; if (act->hotkeys[i] != -1) { int item_id = powers->powers[act->hotkeys[i]].requires_item; if (item_id != -1 && items->items[item_id].type == "consumable") { act->slot_item_count[i] = inv->getItemCountCarried(item_id); if (act->slot_item_count[i] == 0) { act->slot_enabled[i] = false; } } else if (item_id != -1) { // if a non-consumable item power is unequipped, disable that slot if (!inv->isItemEquipped(item_id)) { act->slot_enabled[i] = false; } } } } }
void MenuManager::render() { for (unsigned int i=0; i<menus.size(); i++) { menus[i]->render(); } TooltipData tip_new; // Find tooltips depending on mouse position if (!book->visible) { if (chr->visible && isWithin(chr->window_area,inpt->mouse)) { tip_new = chr->checkTooltip(); } if (vendor->visible && isWithin(vendor->window_area,inpt->mouse)) { tip_new = vendor->checkTooltip(inpt->mouse); } if (stash->visible && isWithin(stash->window_area,inpt->mouse)) { tip_new = stash->checkTooltip(inpt->mouse); } if (pow->visible && isWithin(pow->window_area,inpt->mouse)) { tip_new = pow->checkTooltip(inpt->mouse); } if (inv->visible && !mouse_dragging && isWithin(inv->window_area,inpt->mouse)) { tip_new = inv->checkTooltip(inpt->mouse); } } if (isWithin(act->window_area,inpt->mouse)) { tip_new = act->checkTooltip(inpt->mouse); } if (!tip_new.isEmpty()) { // when we render a tooltip it buffers the rasterized text for performance. // If this new tooltip is the same as the existing one, reuse. if (!tip_new.compare(&tip_buf)) { tip_buf.clear(); tip_buf = tip_new; } tip->render(tip_buf, inpt->mouse, STYLE_FLOAT); TOOLTIP_CONTEXT = TOOLTIP_MENU; } else if (TOOLTIP_CONTEXT != TOOLTIP_MAP) { TOOLTIP_CONTEXT = TOOLTIP_NONE; } if (NO_MOUSE) handleKeyboardTooltips(); // draw icon under cursor if dragging if (mouse_dragging) { if (drag_src == DRAG_SRC_INVENTORY || drag_src == DRAG_SRC_VENDOR || drag_src == DRAG_SRC_STASH) setDragIconItem(drag_stack); else if (drag_src == DRAG_SRC_POWERS || drag_src == DRAG_SRC_ACTIONBAR) setDragIcon(powers->powers[drag_power].icon); renderIcon(inpt->mouse.x - ICON_SIZE/2, inpt->mouse.y - ICON_SIZE/2); } else if (keyboard_dragging) { if (drag_src == DRAG_SRC_INVENTORY || drag_src == DRAG_SRC_VENDOR || drag_src == DRAG_SRC_STASH) setDragIconItem(drag_stack); else if (drag_src == DRAG_SRC_POWERS || drag_src == DRAG_SRC_ACTIONBAR) setDragIcon(powers->powers[drag_power].icon); renderIcon(keydrag_pos.x - ICON_SIZE/2, keydrag_pos.y - ICON_SIZE/2); } }
void MenuManager::logic() { bool clicking_character = false; bool clicking_inventory = false; bool clicking_powers = false; bool clicking_log = false; ItemStack stack; hudlog->logic(); enemy->logic(); chr->logic(); inv->logic(); vendor->logic(); pow->logic(); log->logic(); talker->logic(); // only allow the vendor window to be open if the inventory is open if (vendor->visible && !(inv->visible)) { closeLeft(true); } if (!inpt->pressing[INVENTORY] && !inpt->pressing[POWERS] && !inpt->pressing[CHARACTER] && !inpt->pressing[LOG]) key_lock = false; // check if mouse-clicking a menu button act->checkMenu(inpt->mouse, clicking_character, clicking_inventory, clicking_powers, clicking_log); if (exit->visible) { exit->logic(); if (exit->isExitRequested()) { done = true; } } // exit menu toggle if ((inpt->pressing[CANCEL] && !inpt->lock[CANCEL] && !key_lock && !dragging) && !(stats->corpse && stats->permadeath)) { inpt->lock[CANCEL] = true; key_lock = true; if (menus_open) { closeAll(true); } else { exit->visible = !exit->visible; } } // inventory menu toggle if (((inpt->pressing[INVENTORY] && !key_lock && !dragging) || clicking_inventory) && !stats->transformed) { key_lock = true; if (inv->visible) { closeRight(true); } else { closeRight(false); act->requires_attention[MENU_INVENTORY] = false; inv->visible = true; if (sfx_open) Mix_PlayChannel(-1, sfx_open, 0); } } // powers menu toggle if (((inpt->pressing[POWERS] && !key_lock && !dragging) || clicking_powers) && !stats->transformed) { key_lock = true; if (pow->visible) { closeRight(true); } else { closeRight(false); act->requires_attention[MENU_POWERS] = false; pow->visible = true; if (sfx_open) Mix_PlayChannel(-1, sfx_open, 0); } } // character menu toggleggle if (((inpt->pressing[CHARACTER] && !key_lock && !dragging) || clicking_character) && !stats->transformed) { key_lock = true; if (chr->visible) { closeLeft(true); } else { closeLeft(false); act->requires_attention[MENU_CHARACTER] = false; chr->visible = true; if (sfx_open) Mix_PlayChannel(-1, sfx_open, 0); } } // log menu toggle if (((inpt->pressing[LOG] && !key_lock && !dragging) || clicking_log) && !stats->transformed) { key_lock = true; if (log->visible) { closeLeft(true); } else { closeLeft(false); act->requires_attention[MENU_LOG] = false; log->visible = true; if (sfx_open) Mix_PlayChannel(-1, sfx_open, 0); } } if (MENUS_PAUSE) { pause = (inv->visible || pow->visible || chr->visible || log->visible || vendor->visible || talker->visible); } menus_open = (inv->visible || pow->visible || chr->visible || log->visible || vendor->visible || talker->visible); if (stats->alive) { int offset_x = (VIEW_W - 320); int offset_y = (VIEW_H - 416)/2; // handle right-click if (!dragging && inpt->pressing[MAIN2] && !inpt->lock[MAIN2]) { // exit menu if (exit->visible && isWithin(exit->window_area, inpt->mouse)) { inpt->lock[MAIN2] = true; } // activate inventory item else if (inv->visible && isWithin(inv->window_area, inpt->mouse)) { inpt->lock[MAIN2] = true; if (isWithin(inv->carried_area, inpt->mouse)) { inv->activate(inpt); } } } // handle left-click if (!dragging && inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) { // exit menu if (exit->visible && isWithin(exit->window_area, inpt->mouse)) { inpt->lock[MAIN1] = true; } // left side menu else if (inpt->mouse.x <= 320 && inpt->mouse.y >= offset_y && inpt->mouse.y <= offset_y+416) { if (chr->visible) { inpt->lock[MAIN1] = true; // applied a level-up if (chr->checkUpgrade()) { // apply equipment and max hp/mp inv->applyEquipment(inv->inventory[EQUIPMENT].storage); stats->hp = stats->maxhp; stats->mp = stats->maxmp; } } else if (vendor->visible) { inpt->lock[MAIN1] = true; if (inpt->pressing[CTRL]) { // buy item from a vendor if (!inv->full()) { stack = vendor->click(inpt); if (stack.item > 0) { if( inv->full()) { // Can we say "Not enough place" ? vendor->itemReturn( stack); } else if( ! inv->buy( stack)) { // Can we say "Not enough money" ? (here or in MenuInventory::buy()) vendor->itemReturn( stack); } } } } else { // start dragging a vendor item drag_stack = vendor->click(inpt); if (drag_stack.item > 0) { dragging = true; drag_src = DRAG_SRC_VENDOR; } } } else if(log->visible) { inpt->lock[MAIN1] = true; log->tabsLogic(); } } // right side menu else if (inpt->mouse.x >= offset_x && inpt->mouse.y >= offset_y && inpt->mouse.y <= offset_y+416) { // pick up an inventory item if (inv->visible) { if (inpt->pressing[CTRL]) { inpt->lock[MAIN1] = true; stack = inv->click(inpt); if( stack.item > 0) { if (vendor->visible) { if( vendor->full()) { // Can we say "Not enough place" ? inv->itemReturn( stack); } else { // The vendor could have a limited amount of money in the future. It will be tested here. if (inv->sell(stack)) { vendor->add(stack); } else { inv->itemReturn(stack); } } } else { if (!inv->sell(stack)) { inv->itemReturn(stack); } } } } else { inpt->lock[MAIN1] = true; drag_stack = inv->click(inpt); if (drag_stack.item > 0) { dragging = true; drag_src = DRAG_SRC_INVENTORY; } } } // pick up a power else if (pow->visible) { inpt->lock[MAIN1] = true; drag_power = pow->click(inpt->mouse); if (drag_power > -1) { dragging = true; drag_src = DRAG_SRC_POWERS; } } } // action bar else if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse) || isWithin(act->menuArea, inpt->mouse)) { inpt->lock[MAIN1] = true; // ctrl-click action bar to clear that slot if (inpt->pressing[CTRL] && !stats->transformed) { act->remove(inpt->mouse); } // allow drag-to-rearrange action bar else if (!isWithin(act->menuArea, inpt->mouse) && !stats->transformed) { drag_power = act->checkDrag(inpt->mouse); if (drag_power > -1) { dragging = true; drag_src = DRAG_SRC_ACTIONBAR; } } // else, clicking action bar to use a power? // this check is done by GameEngine when calling Avatar::logic() } } // handle dropping if (dragging && !inpt->pressing[MAIN1]) { // putting a power on the Action Bar if (drag_src == DRAG_SRC_POWERS) { if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse)) { act->drop(inpt->mouse, drag_power, 0); } } // rearranging the action bar else if (drag_src == DRAG_SRC_ACTIONBAR) { if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse)) { act->drop(inpt->mouse, drag_power, 1); } } // rearranging inventory or dropping items else if (drag_src == DRAG_SRC_INVENTORY) { if (inv->visible && inpt->mouse.x >= offset_x && inpt->mouse.y >= offset_y && inpt->mouse.y <= offset_y+416) { inv->drop(inpt->mouse, drag_stack); drag_stack.item = 0; } else if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse)) { // The action bar is not storage! inv->itemReturn(drag_stack); // put an item with a power on the action bar if (items->items[drag_stack.item].power != -1) { act->drop(inpt->mouse, items->items[drag_stack.item].power, false); } } else if (vendor->visible && isWithin(vendor->slots_area, inpt->mouse)) { // vendor sell item if( vendor->full()) { // Can we say "Not enough place" ? inv->itemReturn( drag_stack); } else { if (inv->sell( drag_stack)) { vendor->add( drag_stack); } else { inv->itemReturn(drag_stack); } } drag_stack.item = 0; } else { // if dragging and the source was inventory, drop item to the floor // quest items cannot be dropped if (items->items[drag_stack.item].type != ITEM_TYPE_QUEST) { drop_stack = drag_stack; drag_stack.item = 0; drag_stack.quantity = 0; } else { inv->itemReturn(drag_stack); } } } else if (drag_src == DRAG_SRC_VENDOR) { // dropping an item from vendor (we only allow to drop into the carried area) if (inv->visible && isWithin( inv->carried_area, inpt->mouse)) { if( inv->full()) { // Can we say "Not enough place" ? vendor->itemReturn( drag_stack); } else if( ! inv->buy( drag_stack, inpt->mouse)) { // Can we say "Not enough money" ? (here or in MenuInventory::buy()) vendor->itemReturn( drag_stack); } drag_stack.item = 0; } else { vendor->itemReturn(drag_stack); } } dragging = false; } } // handle equipment changes affecting hero stats if (inv->changed_equipment || inv->changed_artifact) { inv->applyEquipment(inv->inventory[EQUIPMENT].storage); inv->changed_artifact = false; // the equipment flag is reset after the new sprites are loaded } // for action-bar powers that represent items, lookup the current item count for (int i=0; i<12; i++) { act->slot_enabled[i] = true; act->slot_item_count[i] = -1; if (act->hotkeys[i] != -1) { int item_id = powers->powers[act->hotkeys[i]].requires_item; if (item_id != -1 && items->items[item_id].type == ITEM_TYPE_CONSUMABLE) { act->slot_item_count[i] = inv->getItemCountCarried(item_id); if (act->slot_item_count[i] == 0) { act->slot_enabled[i] = false; } } else if (item_id != -1) { // if a non-consumable item power is unequipped, disable that slot if (!inv->isItemEquipped(item_id)) { act->slot_enabled[i] = false; } } } } }
/** * If pressing an action key (keyboard or mouseclick) and the power can be used, * add that power to the action queue */ void MenuActionBar::checkAction(std::vector<ActionData> &action_queue) { // check click and hotkey actions for (unsigned i = 0; i < slots_count; i++) { ActionData action; action.hotkey = i; bool have_aim = false; slot_activated[i] = false; if (!slots[i]) continue; if (slot_enabled[i]) { // part two of two step activation if (static_cast<unsigned>(twostep_slot) == i && inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) { have_aim = true; action.power = hotkeys_mod[i]; twostep_slot = -1; inpt->lock[MAIN1] = true; } // mouse/touch click else if (!NO_MOUSE && slots[i]->checkClick() == ACTIVATED) { have_aim = false; slot_activated[i] = true; action.power = hotkeys_mod[i]; // if a power requires a fixed target (like teleportation), break up activation into two parts // the first step is to mark the slot that was clicked on if (action.power > 0) { const Power &power = powers->getPower(action.power); if (power.starting_pos == STARTING_POS_TARGET || power.buff_teleport) { twostep_slot = i; action.power = 0; } else { twostep_slot = -1; } } } // joystick/keyboard action button else if (inpt->pressing[ACTIONBAR_USE] && static_cast<unsigned>(tablist.getCurrent()) == i) { have_aim = false; slot_activated[i] = true; action.power = hotkeys_mod[i]; twostep_slot = -1; } // pressing hotkey else if (i<10 && inpt->pressing[i+BAR_1]) { have_aim = true; action.power = hotkeys_mod[i]; twostep_slot = -1; } else if (i==10 && inpt->pressing[MAIN1] && !inpt->lock[MAIN1] && !isWithin(window_area, inpt->mouse)) { have_aim = true; action.power = hotkeys_mod[10]; twostep_slot = -1; } else if (i==11 && inpt->pressing[MAIN2] && !inpt->lock[MAIN2] && !isWithin(window_area, inpt->mouse)) { have_aim = true; action.power = hotkeys_mod[11]; twostep_slot = -1; } } // a power slot was activated if (action.power > 0 && static_cast<unsigned>(action.power) < powers->powers.size()) { const Power &power = powers->getPower(action.power); bool can_use_power = true; action.instant_item = (power.new_state == POWSTATE_INSTANT && power.requires_item > 0); // check if we can add this power to the action queue for (unsigned j=0; j<action_queue.size(); j++) { if (action_queue[j].hotkey == i) { // this power is already in the action queue, update its target action_queue[j].target = setTarget(have_aim, power.aim_assist); can_use_power = false; break; } else if (!action.instant_item && !action_queue[j].instant_item) { can_use_power = false; break; } } if (!can_use_power) continue; // set the target depending on how the power was triggered action.target = setTarget(have_aim, power.aim_assist); // add it to the queue action_queue.push_back(action); } else { // if we're not triggering an action that is currently in the queue, // remove it from the queue for (unsigned j=0; j<action_queue.size(); j++) { if (action_queue[j].hotkey == i) action_queue.erase(action_queue.begin()+j); } } } }
void GameStateLoad::logic() { frame_ticker++; if (frame_ticker == 64) frame_ticker = 0; if (frame_ticker < 32) current_frame = frame_ticker / 8; else current_frame = (63 - frame_ticker) / 8; if (button_exit->checkClick()) { requestedGameState = new GameStateTitle(screen, inp, font, msg); } if(loading_requested) { loading = true; loading_requested = false; logicLoading(); } if (button_action->checkClick()) { if (stats[selected_slot].name == "") { // create a new game GameStateNew* newgame = new GameStateNew(screen, inp, font, msg); newgame->game_slot = selected_slot + 1; requestedGameState = newgame; } else { loading_requested = true; } } if (button_alternate->checkClick()) { // Display pop-up to make sure save should be deleted confirm->visible = true; confirm->render(); } if (confirm->visible) { confirm->logic(); if(confirm->confirmClicked) { stringstream filename; filename << PATH_USER << "save" << (selected_slot+1) << ".txt"; if(remove(filename.str().c_str()) != 0) perror("Error deleting save from path"); stats[selected_slot] = StatBlock(); readGameSlot(selected_slot); loadPreview(selected_slot); loadPortrait(selected_slot); button_alternate->enabled = false; button_action->label = msg->get("new_game_button"); confirm->visible = false; confirm->confirmClicked = false; } } // check clicking game slot if (inp->pressing[MAIN1] && !inp->lock[MAIN1]) { for (int i=0; i<GAME_SLOT_MAX; i++) { if (isWithin(slot_pos[i], inp->mouse)) { selected_slot = i; inp->lock[MAIN1] = true; loadPortrait(selected_slot); button_action->enabled = true; if (stats[selected_slot].name == "") { button_action->label = msg->get("new_game_button"); button_alternate->enabled = false; } else { button_action->label = msg->get("load_game_button"); button_alternate->enabled = true; } } } } }
void ListWeatherCloud::renderClouds(){ //if (cycle_i > time_of_rain) renderRainfall(); renderRainfall(); // TODO: remove this line, uncomment previous if ( (clouds_arr_initialized) && (!cloud_list.empty()) ){ std::list<WeatherCloud*>::iterator it=cloud_list.begin(); WeatherCloud *cloud; Sprite *spr_cloud; Point p; FPoint fp; Point dest_p; int i, j, nr=0; i=-RADIUS; j=0; // -> with j=-RADIUS: segmentation faults quite common while (j < RADIUS){ // use a cloud from the list several times if needed if ((it == cloud_list.end())) it=cloud_list.begin(); cloud = *it; if (cloud==NULL){ it++; continue; // break; } spr_cloud = cloud->getSprite(); if (spr_cloud==NULL) break; fp.x = cloud_state[nr][4] + i; fp.y = cloud_state[nr][5] + j; if (!isWithin(mapr->cam,RADIUS + 4,fp)){ // move cloud to the opposite direction direction = calcDirection(mapr->cam.x, mapr->cam.y, fp.x, fp.y); if (direction < 4) direction +=4; else direction -=4; FPoint fpn = calcVector(fp, direction, RADIUS+24); cloud_state[nr][4] = floor(fpn.x) - i; cloud_state[nr][5] = floor(fpn.y) - j; } p = map_to_screen(cloud_state[nr][4] + i, cloud_state[nr][5] + j, mapr->cam.x, mapr->cam.y); if (cycle_i % RENDER_CHANGE_AFTER/2 == 0) { // TODO: should depend on wind direction and perhaps speed; cloud_state[nr][2] = cloud_state[nr][2] + randBetween(1,2); cloud_state[nr][3] = cloud_state[nr][3] + randBetween(1,2); direction = calcDirection(0.0,0.0, cloud_state[nr][2], cloud_state[nr][3]); } // overflow of cloud_state[nr][2] possible, but with little consequences dest_p.x = p.x + (cloud_state[nr][2] % 800) - 400; dest_p.y = p.y + (cloud_state[nr][3] % 600) - 300; spr_cloud->setOffset(cloud_state[nr][1],cloud_state[nr][1]); spr_cloud->setDest(dest_p); render_device->render(spr_cloud); i+=cloud_distance; if (i>RADIUS){ i=-RADIUS; j+=cloud_distance; } it++; nr++; } } }
void trpgPageManager::LodPageInfo::Update() { trpg2iPoint sw,ne; // Figure out the lower left and upper right corners // in cell coordinates sw.x = cell.x - aoiSize.x; sw.y = cell.y - aoiSize.y; ne.x = cell.x + aoiSize.x; ne.y = cell.y + aoiSize.y; sw.x = MAX(0,sw.x); sw.y = MAX(0,sw.y); ne.x = MIN(lodSize.x-1,ne.x); ne.y = MIN(lodSize.y-1,ne.y); /* Load list - Some of the tiles we're supposed to load may now be out of range. Take them off the load list. */ unsigned int i; for (i=0;i<load.size();i++) { if (load[i] && !isWithin(load[i],sw,ne)) { freeList.push_back(load[i]); load[i] = NULL; } } /* Unload list - Some of the tiles we were planning on unloading may now be in view again. Move them back to current. */ for (i=0;i<unload.size();i++) { if (unload[i] && isWithin(unload[i],sw,ne)) { current.push_back(unload[i]); unload[i] = NULL; } } /* Current list - We need to figure out a few things here. 1) What's in the current list that should be paged out. 2) What's already paged, sorted into tmpCurrent. 3) What's missing from tmpCurrent and should be paged in. */ // Look for tiles to page out // Move them to the unload list for (i=0;i<current.size();i++) { if (current[i] && !isWithin(current[i],sw,ne)) { unload.push_back(current[i]); current[i] = NULL; } } // Clean the NULLs out of the current list int curPos = 0; for (i=0;i<current.size();i++) { if (current[i]) { current[curPos] = current[i]; curPos++; } } current.resize(curPos); bool doUpdate = true; if(majorVersion == 2 && minorVersion >= 1) { // Version 2.1, we update only lod 0 since the tile table // will only contain lod 0. All tiles from other lod must be // update through the trpgPageManager::AckLoad(tile info) if(lod != 0) doUpdate = false; } if(doUpdate) { // Sort the currently loaded stuff into a spatial array // so we can figure out what needs to be loaded in addition. int dx,dy; dx = ne.x - sw.x+1; dy = ne.y - sw.y+1; tmpCurrent.resize(dx*dy); for (i=0;i<tmpCurrent.size();i++) tmpCurrent[i] = false; for (i=0;i<current.size();i++) { trpgManagedTile *tile = current[i]; if (tile) { int tileX,tileY,tileLod; tile->GetTileLoc(tileX,tileY,tileLod); tmpCurrent[(tileY-sw.y)*dx + (tileX-sw.x)] = true; } } // Now figure out which ones are missing and add them // to the load list for (int x=0;x<dx;x++) { for (int y=0;y<dy;y++) { if (!tmpCurrent[y*dx + x]) { // Allocate a new tile trpgManagedTile *tile = NULL; if (freeList.size() > 0) { tile = freeList[0]; freeList.pop_front(); } else tile = new trpgManagedTile(); tile->SetTileLoc(x+sw.x,y+sw.y,lod); trpgwAppAddress addr; float32 zmin, zmax; if(tileTable && tileTable->GetTile(x+sw.x, y+sw.y, lod, addr, zmin, zmax)) tile->SetTileAddress(addr); load.push_back(tile); } } } } // That's it. All the rest is handled by the caller // iterating through the tiles to load and unload. }