SORE_Graphics::render_list& SORE_Graphics::RenderPipe::beginRender ( const camera_table& cameras, Renderbuffer_map_t& renderBuffers, render_list& list, GLCommandList& renderQueue, BufferManager* bm ) { PROFILE_BLOCK("Render pipe", profiler); if(cameras.find(camera) == cameras.end()) { // TODO: FIXME: sore exceptions throw std::runtime_error("Could not find named camera " + camera); } const camera_info& cam = cameras.find(camera)->second; BOOST_FOREACH(const Renderable& r, list) { SORE_Graphics::geometry_entry ge; { PROFILE_BLOCK("Look up GC", profiler); ge = bm->LookupGC(r.GetGeometryChunk()); } { PROFILE_BLOCK("Add renderables", profiler); renderQueue.AddRenderable(r, ge, cam); } }
void offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta, ClipperLib::JoinType joinType, double miterLimit) { PROFILE_FUNC(); // read input ClipperLib::Paths input; Slic3rMultiPoints_to_ClipperPaths(polygons, &input); // scale input scaleClipperPolygons(input); // perform offset ClipperLib::ClipperOffset co; if (joinType == jtRound) { co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE); } else { co.MiterLimit = miterLimit; } { PROFILE_BLOCK(offset_AddPaths); co.AddPaths(input, joinType, ClipperLib::etClosedPolygon); } { PROFILE_BLOCK(offset_Execute); co.Execute(*retval, delta * float(CLIPPER_OFFSET_SCALE)); } // unscale output unscaleClipperPolygons(*retval); }
void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, ClipperLib::PolyTree* retval, const ClipperLib::PolyFillType fillType, const bool safety_offset_) { PROFILE_BLOCK(_clipper_do_polylines); // read input ClipperLib::Paths input_subject, input_clip; Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject); Slic3rMultiPoints_to_ClipperPaths(clip, &input_clip); // perform safety offset if (safety_offset_) safety_offset(&input_clip); // init Clipper ClipperLib::Clipper clipper; clipper.Clear(); // add polygons { PROFILE_BLOCK(_clipper_do_polylines_AddPaths); clipper.AddPaths(input_subject, ClipperLib::ptSubject, false); clipper.AddPaths(input_clip, ClipperLib::ptClip, true); } // perform operation { PROFILE_BLOCK(_clipper_do_polylines_Execute); clipper.Execute(clipType, *retval, fillType, fillType); } }
void safety_offset(ClipperLib::Paths* paths) { PROFILE_FUNC(); // scale input scaleClipperPolygons(*paths); // perform offset (delta = scale 1e-05) ClipperLib::ClipperOffset co; #ifdef CLIPPER_UTILS_DEBUG if (clipper_export_enabled) { static int iRun = 0; export_clipper_input_polygons_bin(debug_out_path("safety_offset-polygons-%d", ++iRun).c_str(), *paths, ClipperLib::Paths()); } #endif /* CLIPPER_UTILS_DEBUG */ ClipperLib::Paths out; for (size_t i = 0; i < paths->size(); ++ i) { ClipperLib::Path &path = (*paths)[i]; co.Clear(); co.MiterLimit = 2; bool ccw = ClipperLib::Orientation(path); if (! ccw) std::reverse(path.begin(), path.end()); { PROFILE_BLOCK(safety_offset_AddPaths); co.AddPath((*paths)[i], ClipperLib::jtMiter, ClipperLib::etClosedPolygon); } { PROFILE_BLOCK(safety_offset_Execute); // offset outside by 10um ClipperLib::Paths out_this; co.Execute(out_this, ccw ? 10.f * float(CLIPPER_OFFSET_SCALE) : -10.f * float(CLIPPER_OFFSET_SCALE)); if (! ccw) { // Reverse the resulting contours once again. for (ClipperLib::Paths::iterator it = out_this.begin(); it != out_this.end(); ++ it) std::reverse(it->begin(), it->end()); } if (out.empty()) out = std::move(out_this); else std::move(std::begin(out_this), std::end(out_this), std::back_inserter(out)); } } *paths = std::move(out); // unscale output unscaleClipperPolygons(*paths); }
void rebuild_chunks(App *app) { PROFILE_BLOCK("Unload Chunk", app->chunk_cache_count); for (u32 i=0; i<app->chunk_cache_count; i++) { TerrainChunk *chunk = app->chunk_cache + i; unload_chunk(chunk); } }
int FileSystemWatcherTask::task() { m_handle = CreateFile(m_path, FILE_LIST_DIRECTORY, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr); if (m_handle == INVALID_HANDLE_VALUE) return -1; Lumix::setMemory(&m_overlapped, 0, sizeof(m_overlapped)); m_overlapped.hEvent = this; m_finished = false; while (!m_finished) { PROFILE_BLOCK("Change handling"); BOOL status = ReadDirectoryChangesW(m_handle, m_info, sizeof(m_info), TRUE, READ_DIR_CHANGE_FILTER, &m_received, &m_overlapped, ¬if); if (status == FALSE) break; SleepEx(INFINITE, TRUE); } return 0; }
void handleEvents() { PROFILE_FUNCTION(); { PROFILE_BLOCK("qt::processEvents"); m_qt_app->processEvents(); } }
void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, T* retval, const ClipperLib::PolyFillType fillType, const bool safety_offset_) { PROFILE_BLOCK(_clipper_do_polygons); // read input ClipperLib::Paths input_subject, input_clip; Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject); Slic3rMultiPoints_to_ClipperPaths(clip, &input_clip); // perform safety offset if (safety_offset_) { if (clipType == ClipperLib::ctUnion) { safety_offset(&input_subject); } else { safety_offset(&input_clip); } } // init Clipper ClipperLib::Clipper clipper; clipper.Clear(); // add polygons { PROFILE_BLOCK(_clipper_do_polygons_AddPaths); clipper.AddPaths(input_subject, ClipperLib::ptSubject, true); clipper.AddPaths(input_clip, ClipperLib::ptClip, true); #ifdef CLIPPER_UTILS_DEBUG if (clipper_export_enabled) { static int iRun = 0; export_clipper_input_polygons_bin(debug_out_path("_clipper_do_polygons_AddPaths-polygons-%d", ++iRun).c_str(), input_subject, input_clip); } #endif /* CLIPPER_UTILS_DEBUG */ } // perform operation { PROFILE_BLOCK(_clipper_do_polygons_Execute); clipper.Execute(clipType, *retval, fillType, fillType); } }
int Scheduler::task() { while (!isForceExit()) { m_data_event.wait(); PROFILE_BLOCK("Schedule") m_manager.doScheduling(); } return 0; }
void frame() { float frame_time = m_frame_timer->tick(); m_engine->update(*m_universe); m_pipeline->render(); auto* renderer = m_engine->getPluginManager().getPlugin("renderer"); static_cast<Lumix::Renderer*>(renderer)->frame(); m_engine->getFileSystem().updateAsyncTransactions(); if (frame_time < 1 / 60.0f) { PROFILE_BLOCK("sleep"); Lumix::MT::sleep(Lumix::uint32(1000 / 60.0f - frame_time * 1000)); } handleEvents(); }
SORE_Graphics::render_list& SORE_Graphics::SortingPipe::beginRender ( const camera_table& cameras, Renderbuffer_map_t& renderbuffers, render_list& list, GLCommandList& renderQueue, BufferManager* bm ) { PROFILE_BLOCK("Sorting pipe", profiler); sortedList = list; std::sort(sortedList.begin(), sortedList.end(), comparator); return sortedList; }
void Item::tick(Position position) { PROFILE_BLOCK("Item::tick"); if (fire->isBurning()) { INFO << getName() << " burning "; position.fireDamage(0.2); modViewObject().setModifier(ViewObject::Modifier::BURNING); fire->tick(); if (!fire->isBurning()) { position.globalMessage(getTheName() + " burns out"); discarded = true; } } specialTick(position); if (timeout) { if (position.getGame()->getGlobalTime() >= *timeout) { discarded = true; } } }
void run() { while (m_main_window->isVisible()) { { PROFILE_BLOCK("tick"); m_engine->update(*m_universe_context); m_pipeline->render(); if (!m_engine->getResourceManager().isLoading()) { if (!nextTest()) return; } m_engine->getFileSystem().updateAsyncTransactions(); handleEvents(); } Lumix::g_profiler.frame(); } }
std::string cache_read() { PROFILE_FUNC(); std::string data; PROFILE_START(action_find); // Starts new action which will be inner to ACTION_READ bool found = find_record(); PROFILE_STOP(action_find); if (!found) { PROFILE_BLOCK(load_from_disk); data = read_from_disk(); put_into_cache(data); return data; // Here all action guards are destructed and actions are correctly finished } data = load_from_cache(); return data; }
void updateAsyncTransactions() override { PROFILE_FUNCTION(); while (!m_in_progress.empty()) { AsynTrans* tr = m_in_progress.front(); if (!tr->isCompleted()) break; PROFILE_BLOCK("processAsyncTransaction"); m_in_progress.pop(); tr->data.m_cb.invoke(*tr->data.m_file, !!(tr->data.m_flags & E_SUCCESS)); if ((tr->data.m_flags & (E_SUCCESS | E_FAIL)) != 0) { closeAsync(*tr->data.m_file); } m_transaction_queue.dealoc(tr); } int32 can_add = C_MAX_TRANS - m_in_progress.size(); while (can_add && !m_pending.empty()) { AsynTrans* tr = m_transaction_queue.alloc(false); if (tr) { AsyncItem& item = m_pending[0]; tr->data.m_file = item.m_file; tr->data.m_cb = item.m_cb; tr->data.m_mode = item.m_mode; copyString(tr->data.m_path, sizeof(tr->data.m_path), item.m_path); tr->data.m_flags = item.m_flags; tr->reset(); m_transaction_queue.push(tr, true); m_in_progress.push(tr); m_pending.erase(0); } can_add--; } }
astra_status_t device_streamset::read() { PROFILE_BLOCK(streamset_read); if (!isOpen_ || niActiveStreams_.size() == 0) return ASTRA_STATUS_SUCCESS; int streamIndex = -1; int timeout = openni::TIMEOUT_NONE; int i = 0; openni::Status rc; for(i = 0; i < niActiveStreams_.size(); i++) { rc = openni::OpenNI::waitForAnyStream(&niActiveStreams_.data()[i], 1, &streamIndex, timeout); if (streamIndex != -1) { auto stream = astraActiveStreams_[i]; stream->read(frameIndex_); } if (streamIndex == 0) { //only increment frameIndex with primary stream //TODO this won't work when streams have different target FPS frameIndex_++; } } if (rc == openni::STATUS_TIME_OUT) { return ASTRA_STATUS_TIMEOUT; } return ASTRA_STATUS_SUCCESS; }
int task() { while (!m_trans_queue->isAborted()) { PROFILE_BLOCK("transaction"); AsynTrans* tr = m_trans_queue->pop(true); if (!tr) break; if ((tr->data.m_flags & E_IS_OPEN) == E_IS_OPEN) { tr->data.m_flags |= tr->data.m_file->open(Path(tr->data.m_path), tr->data.m_mode) ? E_SUCCESS : E_FAIL; } else if ((tr->data.m_flags & E_CLOSE) == E_CLOSE) { tr->data.m_file->close(); tr->data.m_file->release(); tr->data.m_file = nullptr; } tr->setCompleted(); } return 0; }
void update(UniverseContext& context) override { PROFILE_FUNCTION(); float dt; ++m_fps_frame; if (m_fps_timer->getTimeSinceTick() > 0.5f) { m_fps = m_fps_frame / m_fps_timer->tick(); m_fps_frame = 0; } dt = m_timer->tick(); m_last_time_delta = dt; { PROFILE_BLOCK("update scenes"); for (int i = 0; i < context.m_scenes.size(); ++i) { context.m_scenes[i]->update(dt); } } m_plugin_manager->update(dt); m_input_system->update(dt); getFileSystem().updateAsyncTransactions(); }
const char* GCodeReader::parse_line_internal(const char *ptr, GCodeLine &gline, std::pair<const char*, const char*> &command) { PROFILE_FUNC(); // command and args const char *c = ptr; { PROFILE_BLOCK(command_and_args); // Skip the whitespaces. command.first = skip_whitespaces(c); // Skip the command. c = command.second = skip_word(command.first); // Up to the end of line or comment. while (! is_end_of_gcode_line(*c)) { // Skip whitespaces. c = skip_whitespaces(c); if (is_end_of_gcode_line(*c)) break; // Check the name of the axis. Axis axis = NUM_AXES; switch (*c) { case 'X': axis = X; break; case 'Y': axis = Y; break; case 'Z': axis = Z; break; case 'F': axis = F; break; default: if (*c == m_extrusion_axis) axis = E; break; } if (axis != NUM_AXES) { // Try to parse the numeric value. char *pend = nullptr; double v = strtod(++ c, &pend); if (pend != nullptr && is_end_of_word(*pend)) { // The axis value has been parsed correctly. gline.m_axis[int(axis)] = float(v); gline.m_mask |= 1 << int(axis); c = pend; } else // Skip the rest of the word. c = skip_word(c); } else // Skip the rest of the word. c = skip_word(c); } } if (gline.has(E) && m_config.use_relative_e_distances) m_position[E] = 0; // Skip the rest of the line. for (; ! is_end_of_line(*c); ++ c); // Copy the raw string including the comment, without the trailing newlines. if (c > ptr) { PROFILE_BLOCK(copy_raw_string); gline.m_raw.assign(ptr, c); } // Skip the trailing newlines. if (*c == '\r') ++ c; if (*c == '\n') ++ c; if (m_verbose) std::cout << gline.m_raw << std::endl; return c; }
void generate_ground(Model *model, int chunk_x, int chunk_y, float detail) { PROFILE_BLOCK("Generate Ground"); int size_x = CHUNK_SIZE_X; int size_y = CHUNK_SIZE_Y; int offset_x = chunk_x * size_x; int offset_y = chunk_y * size_y; int width = size_x * detail + 1; int height = size_y * detail + 1; u32 vertices_count = width * height * 3; u32 normals_count = vertices_count; u32 colors_count = vertices_count; u32 indices_count = (width - 1) * (height - 1) * 6; Mesh mesh = {}; allocate_mesh(&mesh, vertices_count, normals_count, indices_count, 0, colors_count); u32 vertices_index = 0; u32 colors_index = 0; u32 normals_index = 0; u32 indices_index = 0; float radius = 0.0f; for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { float x_coord = (float)(x) / detail; float y_coord = (float)(y) / detail; float value = get_terrain_height_at(x_coord + offset_x, y_coord + offset_y); mesh.data.vertices[vertices_index++] = x_coord; mesh.data.vertices[vertices_index++] = value; mesh.data.vertices[vertices_index++] = y_coord; vec3 color = vec3(0.4392f, 0.4588f, 0.3412f); if (value < 7.0f) { color = vec3(0.8118f, 0.5686f, 0.3804f); } mesh.data.colors[colors_index++] = color.r; mesh.data.colors[colors_index++] = color.g; mesh.data.colors[colors_index++] = color.b; // TODO(sedivy): calculate center float distance = glm::length(vec3(x_coord, value, y_coord)); if (distance > radius) { radius = distance; } mesh.data.normals[normals_index++] = 0.0f; mesh.data.normals[normals_index++] = 0.0f; mesh.data.normals[normals_index++] = 0.0f; } } for (int i=0; i<height - 1; i++) { for (int l=0; l<width - 1; l++) { mesh.data.indices[indices_index++] = (height * l + i + 0); mesh.data.indices[indices_index++] = (height * l + i + 1); mesh.data.indices[indices_index++] = (height * l + i + height); mesh.data.indices[indices_index++] = (height * l + i + height); mesh.data.indices[indices_index++] = (height * l + i + 1); mesh.data.indices[indices_index++] = (height * l + i + height + 1); } } for (u32 i=0; i<indices_count; i += 3) { int indices_a = mesh.data.indices[i + 0] * 3; int indices_b = mesh.data.indices[i + 1] * 3; int indices_c = mesh.data.indices[i + 2] * 3; vec3 v0 = vec3(mesh.data.vertices[indices_a + 0], mesh.data.vertices[indices_a + 1], mesh.data.vertices[indices_a + 2]); vec3 v1 = vec3(mesh.data.vertices[indices_b + 0], mesh.data.vertices[indices_b + 1], mesh.data.vertices[indices_b + 2]); vec3 v2 = vec3(mesh.data.vertices[indices_c + 0], mesh.data.vertices[indices_c + 1], mesh.data.vertices[indices_c + 2]); vec3 normal = glm::normalize(glm::cross(v2 - v0, v1 - v0)); mesh.data.normals[indices_a + 0] = -normal.x; mesh.data.normals[indices_a + 1] = -normal.y; mesh.data.normals[indices_a + 2] = -normal.z; mesh.data.normals[indices_b + 0] = -normal.x; mesh.data.normals[indices_b + 1] = -normal.y; mesh.data.normals[indices_b + 2] = -normal.z; mesh.data.normals[indices_c + 0] = -normal.x; mesh.data.normals[indices_c + 1] = -normal.y; mesh.data.normals[indices_c + 2] = -normal.z; } for (u32 i=0; i<normals_count / 3; i += 3) { float x = mesh.data.normals[i + 0]; float y = mesh.data.normals[i + 1]; float z = mesh.data.normals[i + 2]; vec3 normal = glm::normalize(vec3(x, y, z)); mesh.data.normals[i + 0] = normal.x; mesh.data.normals[i + 1] = normal.y; mesh.data.normals[i + 2] = normal.z; } model->id_name = allocate_string("chunk"); model->mesh = mesh; model->radius = radius; }
void SORE_Graphics::SortingPipe::doSetup(Renderbuffer_map_t& renderBuffers) { PROFILE_BLOCK("Sorting pipe", profiler); sortedList.clear(); }
virtual void endFrame() { PROFILE_BLOCK("fps_limiter"); WaitForSingleObject(m_timer, 1000 / m_fps); }
int main(int argc, char **argv) { MemStartCheck(); { char* test = new char[16]; delete[] test; } grinliz::TestContainers(); { grinliz::GLString releasePath; GetSystemPath(GAME_SAVE_DIR, "release_log.txt", &releasePath); SetReleaseLog(fopen(releasePath.c_str(), "w")); } GLOUTPUT_REL(("Altera startup. version'%s'\n", VERSION)); SDL_version compiled; SDL_version linked; SDL_VERSION(&compiled); SDL_GetVersion(&linked); GLOUTPUT_REL(("SDL version compiled: %d.%d.%d\n", compiled.major, compiled.minor, compiled.patch)); GLOUTPUT_REL(("SDL version linked: %d.%d.%d\n", linked.major, linked.minor, linked.patch)); GLASSERT((linked.major == compiled.major && linked.minor == compiled.minor)); // SDL initialization steps. if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE | SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_EVENTS) < 0) { fprintf(stderr, "SDL initialization failed: %s\n", SDL_GetError()); exit(1); } // OpenGL 4.3 provides full compatibility with OpenGL ES 3.0. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); #ifdef DEBUG #if 0 // I was hoping to get to Angle on intel - may still be able to. But // as is this gets HW mode, which crashes in a function that should // be supported. The Intel drivers are so terrible. As of this writing, // you can't specify the DX version of ES: // http://forums.libsdl.org/viewtopic.php?t=9770&highlight=angle+opengl SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); // driver supports 2 and 3. Both crash. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif #if 0 // 3.0 context. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif #if 0 // The trickier 3.2 context. // No GL_QUADs anymore. // All the attributes need to be floats. // No ALPHA textures. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); #endif #if 0 // In theory the minimum supported version: // has instancing, and modern shader syntax SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); #endif #if 0 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif #endif if (multisample) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multisample); } SDL_DisplayMode displayMode; SDL_GetCurrentDisplayMode(0, &displayMode); int screenX = displayMode.w / 8; int screenY = displayMode.h / 8; int screenWidth = displayMode.w * 3 / 4; int screenHeight = displayMode.h * 3 / 4; if (argc == 3) { screenWidth = atoi(argv[1]); screenHeight = atoi(argv[2]); if (screenWidth <= 0) screenWidth = SCREEN_WIDTH; if (screenHeight <= 0) screenHeight = SCREEN_HEIGHT; } restoreWidth = screenWidth; restoreHeight = screenHeight; SDL_Window *screen = SDL_CreateWindow("Altera", screenX, screenY, screenWidth, screenHeight, /*SDL_WINDOW_FULLSCREEN | */ SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); GLASSERT(screen); SDL_GL_CreateContext(screen); int stencil = 0; int depth = 0; CHECK_GL_ERROR; SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil); SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth); glGetError(); // the above stencil/depth query sometimes does throw an error. glGetError(); // 2 queries, 2 errors. CHECK_GL_ERROR; GLOUTPUT_REL(("SDL screen created. stencil=%d depthBits=%d\n", stencil, depth)); /* Verify there is a surface */ if (!screen) { fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError()); exit(1); } CHECK_GL_ERROR; glewExperimental = GL_TRUE; int r = glewInit(); GLASSERT(r == GL_NO_ERROR); (void)r; while (glGetError() != GL_NO_ERROR) { // around again } CHECK_GL_ERROR; const unsigned char* vendor = glGetString(GL_VENDOR); const unsigned char* renderer = glGetString(GL_RENDERER); const unsigned char* version = glGetString(GL_VERSION); GLOUTPUT_REL(("OpenGL vendor: '%s' Renderer: '%s' Version: '%s'\n", vendor, renderer, version)); CHECK_GL_ERROR; bool done = false; bool zooming = false; SDL_Event event; grinliz::Vector2I mouseDown = { 0, 0 }; grinliz::Vector2I rightMouseDown = { 0, 0 }; int zoomX = 0; int zoomY = 0; // Used to compute fingers close, but problems: // - really to the OS to do that, because of all the tuning // - the coordinates are in windows normalized, so can't get the physical distance reliably. //bool fingersClose = true; int nFingers = 0; void* game = NewGame(screenWidth, screenHeight, 0); int modKeys = SDL_GetModState(); U32 tickTimer = 0, lastTick = 0, thisTick = 0; #ifdef OUTPUT_MOUSE_AND_TOUCH int value = GetSystemMetrics(SM_DIGITIZER); if (value & NID_INTEGRATED_TOUCH) GLOUTPUT(("NID_INTEGRATED_TOUCH\n")); if (value & NID_MULTI_INPUT) GLOUTPUT(("NID_MULTI_INPUT\n")); if (value & NID_READY) GLOUTPUT(("NID_READY\n")); #endif grinliz::Vector2F multiTouchStart = { 0, 0 }; // ---- Main Loop --- // while (!done) { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_WINDOWEVENT: if (event.window.event == SDL_WINDOWEVENT_RESIZED) { screenWidth = event.window.data1; screenHeight = event.window.data2; GameDeviceLoss(game); GameResize(game, screenWidth, screenHeight, 0); } break; case SDL_KEYUP: switch (event.key.keysym.scancode) { case SDL_SCANCODE_LCTRL: modKeys = modKeys & (~KMOD_LCTRL); break; case SDL_SCANCODE_RCTRL: modKeys = modKeys & (~KMOD_RCTRL); break; case SDL_SCANCODE_LSHIFT: modKeys = modKeys & (~KMOD_LSHIFT); break; case SDL_SCANCODE_RSHIFT: modKeys = modKeys & (~KMOD_RSHIFT); break; default: break; } break; case SDL_KEYDOWN: { // sym or scancode? I used a dvorak keyboard, so appreciate // every day the difference. However, AWSD support is the // primary thing so scancode is hopefully the better choice. switch (event.key.keysym.scancode) { case SDL_SCANCODE_LCTRL: modKeys = modKeys | KMOD_LCTRL; break; case SDL_SCANCODE_RCTRL: modKeys = modKeys | KMOD_RCTRL; break; case SDL_SCANCODE_LSHIFT: modKeys = modKeys | KMOD_LSHIFT; break; case SDL_SCANCODE_RSHIFT: modKeys = modKeys | KMOD_RSHIFT; break; case SDL_SCANCODE_F4: { int sdlMod = SDL_GetModState(); if (sdlMod & (KMOD_RALT | KMOD_LALT)) done = true; } break; case SDL_SCANCODE_ESCAPE: GameHotKey(game, GAME_HK_ESCAPE); break; case SDL_SCANCODE_SPACE: GameHotKey(game, GAME_HK_TOGGLE_PAUSE); break; case SDL_SCANCODE_RETURN: GameHotKey(game, GAME_HK_DEBUG_ACTION); break; case SDL_SCANCODE_F1: GameHotKey(game, GAME_HK_TOGGLE_DEBUG_TEXT); break; case SDL_SCANCODE_F2: GameHotKey(game, GAME_HK_TOGGLE_DEBUG_UI); break; // F3: screenshot case SDL_SCANCODE_TAB: GameHotKey(game, GAME_HK_CAMERA_TOGGLE); break; case SDL_SCANCODE_HOME: GameHotKey(game, GAME_HK_CAMERA_CORE); break; case SDL_SCANCODE_END: GameHotKey(game, GAME_HK_CAMERA_AVATAR); break; case SDL_SCANCODE_PAGEUP: GameHotKey(game, GAME_HK_TELEPORT_AVATAR); break; //case SDLK_a: reserved case SDL_SCANCODE_B: GameHotKey(game, GAME_HK_CHEAT_GOLD); break; case SDL_SCANCODE_C: GameHotKey(game, GAME_HK_ATTACH_CORE); break; //case SDLK_d: reserved case SDL_SCANCODE_E: GameHotKey(game, GAME_HK_CHEAT_ELIXIR); break; case SDL_SCANCODE_H: GameHotKey(game, GAME_HK_TOGGLE_PATHING); break; case SDL_SCANCODE_I: GameHotKey(game, GAME_HK_TOGGLE_AI_DEBUG); break; case SDL_SCANCODE_K: GameHotKey(game, GAME_HK_CHEAT_CRYSTAL); break; case SDL_SCANCODE_M: GameHotKey(game, GAME_HK_MAP); break; case SDL_SCANCODE_P: GameHotKey(game, GAME_HK_TOGGLE_PERF); break; case SDL_SCANCODE_Q: GameHotKey(game, GAME_HK_CHEAT_HERD); break; //case SDLK_s: reserved case SDL_SCANCODE_T: GameHotKey(game, GAME_HK_CHEAT_TECH); break; case SDL_SCANCODE_U: GameHotKey(game, GAME_HK_TOGGLE_UI); break; //case SDLK_w: reserved case SDL_SCANCODE_1: GameHotKey(game, GAME_HK_TOGGLE_GLOW); break; case SDL_SCANCODE_2: GameHotKey(game, GAME_HK_TOGGLE_PARTICLE); break; case SDL_SCANCODE_3: GameHotKey(game, GAME_HK_TOGGLE_VOXEL); break; case SDL_SCANCODE_4: GameHotKey(game, GAME_HK_TOGGLE_SHADOW); break; case SDL_SCANCODE_5: GameHotKey(game, GAME_HK_TOGGLE_BOLT); break; case SDL_SCANCODE_F3: GameDoTick(game, SDL_GetTicks()); SDL_GL_SwapWindow(screen); ScreenCapture(); break; case SDL_SCANCODE_F11: { if (fullscreen) { // SDL_RestoreWindow doesn't seem to work as I expect. SDL_SetWindowFullscreen(screen, 0); SDL_SetWindowSize(screen, restoreWidth, restoreHeight); fullscreen = false; } else { restoreWidth = screenWidth; restoreHeight = screenHeight; SDL_SetWindowFullscreen(screen, SDL_WINDOW_FULLSCREEN_DESKTOP); fullscreen = true; } } break; default: break; } } break; case SDL_MOUSEBUTTONDOWN: { int x = event.button.x; int y = event.button.y; int mod = 0; if (modKeys & (KMOD_LSHIFT | KMOD_RSHIFT)) mod = GAME_TAP_MOD_SHIFT; else if (modKeys & (KMOD_LCTRL | KMOD_RCTRL)) mod = GAME_TAP_MOD_CTRL; if (nFingers > 1) { // do nothing } else if (event.button.button == SDL_BUTTON_LEFT) { #ifdef OUTPUT_MOUSE_AND_TOUCH GLOUTPUT(("Left mouse down %d %d\n", x, y)); #endif mouseDown.Set(event.button.x, event.button.y); GameTap(game, GAME_TAP_DOWN, x, y, mod); } else if (event.button.button == SDL_BUTTON_RIGHT) { #ifdef OUTPUT_MOUSE_AND_TOUCH GLOUTPUT(("Right mouse down %d %d\n", x, y)); #endif GameTap(game, GAME_TAP_CANCEL, x, y, mod); rightMouseDown.Zero(); if (mod == 0) { rightMouseDown.Set(event.button.x, event.button.y); GameCameraPan(game, GAME_PAN_START, float(x), float(y)); } else if (mod == GAME_TAP_MOD_CTRL) { zooming = true; //GameCameraRotate( game, GAME_ROTATE_START, 0.0f ); SDL_GetRelativeMouseState(&zoomX, &zoomY); } } } break; case SDL_MOUSEBUTTONUP: { int x = event.button.x; int y = event.button.y; if (event.button.button == SDL_BUTTON_RIGHT) { #ifdef OUTPUT_MOUSE_AND_TOUCH GLOUTPUT(("Right mouse up %d %d\n", x, y)); #endif zooming = false; if (!rightMouseDown.IsZero()) { GameCameraPan(game, GAME_PAN_END, float(x), float(y)); rightMouseDown.Zero(); } } if (event.button.button == SDL_BUTTON_LEFT) { if (!mouseDown.IsZero()) { // filter out mouse events that become finger events. #ifdef OUTPUT_MOUSE_AND_TOUCH GLOUTPUT(("Left mouse up %d %d\n", x, y)); #endif int mod = 0; if (modKeys & (KMOD_LSHIFT | KMOD_RSHIFT)) mod = GAME_TAP_MOD_SHIFT; else if (modKeys & (KMOD_LCTRL | KMOD_RCTRL)) mod = GAME_TAP_MOD_CTRL; GameTap(game, GAME_TAP_UP, x, y, mod); } } } break; case SDL_MOUSEMOTION: { SDL_GetRelativeMouseState(&zoomX, &zoomY); int state = event.motion.state; int x = event.motion.x; int y = event.motion.y; int mod = 0; if (modKeys & (KMOD_LSHIFT | KMOD_RSHIFT)) mod = GAME_TAP_MOD_SHIFT; else if (modKeys & (KMOD_LCTRL | KMOD_RCTRL)) mod = GAME_TAP_MOD_CTRL; if (nFingers > 1) { // Do nothing. // Multi touch in progress. } else if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) { if (!mouseDown.IsZero()) { #ifdef OUTPUT_MOUSE_AND_TOUCH GLOUTPUT(("Left Mouse move %d %d\n", x, y)); #endif GameTap(game, GAME_TAP_MOVE, x, y, mod); // mouseMoveCount = 0; } } else if (!rightMouseDown.IsZero()) { GLASSERT(state & SDL_BUTTON(SDL_BUTTON_RIGHT)); GameCameraPan(game, GAME_PAN_END, float(x), float(y)); } else if (zooming && (state & SDL_BUTTON(SDL_BUTTON_RIGHT))) { float deltaZoom = 0.01f * (float)zoomY; GameZoom(game, GAME_ZOOM_DISTANCE, deltaZoom); GameCameraRotate(game, (float)(zoomX)*0.5f); } else if (state ==0) { GameTap(game, GAME_MOVE_WHILE_UP, x, y, mod); } } break; case SDL_MOUSEWHEEL: { if (event.wheel.y) { float deltaZoom = -0.1f * float(event.wheel.y); GameZoom(game, GAME_ZOOM_DISTANCE, deltaZoom); } } break; case SDL_FINGERUP: { const SDL_TouchFingerEvent* tfe = &event.tfinger; nFingers = SDL_GetNumTouchFingers(tfe->touchId); if (nFingers < 2 && !multiTouchStart.IsZero()) { #ifdef OUTPUT_MOUSE_AND_TOUCH GLOUTPUT(("2 finger END.\n")); #endif multiTouchStart.Zero(); } } break; case SDL_FINGERDOWN: { const SDL_TouchFingerEvent* tfe = &event.tfinger; nFingers = SDL_GetNumTouchFingers(tfe->touchId); if (nFingers > 1) { if (!mouseDown.IsZero()) { // Wrap up the existing action. #ifdef OUTPUT_MOUSE_AND_TOUCH GLOUTPUT(("Switch to gesture.\n")); #endif mouseDown.Zero(); } } } break; case SDL_MULTIGESTURE: { const SDL_MultiGestureEvent* mge = &event.mgesture; nFingers = SDL_GetNumTouchFingers(mge->touchId); if (nFingers > 1 && multiTouchStart.IsZero()) { #ifdef OUTPUT_MOUSE_AND_TOUCH GLOUTPUT(("2 finger START.\n")); #endif multiTouchStart.Set(mge->x, mge->y); } else if (!multiTouchStart.IsZero()) { // The Pan interacts badly with zoom and rotated. So instead of a continuous, // multi-event action do a bunch of "mini pans". GameCameraPan(game, GAME_PAN_START, multiTouchStart.x * float(screenWidth), multiTouchStart.y*float(screenHeight)); multiTouchStart.Set(mge->x, mge->y); GameCameraPan(game, GAME_PAN_MOVE, multiTouchStart.x * float(screenWidth), multiTouchStart.y*float(screenHeight)); GameCameraPan(game, GAME_PAN_END, multiTouchStart.x * float(screenWidth), multiTouchStart.y*float(screenHeight)); } if (nFingers == 2) { GameZoom(game, GAME_ZOOM_DISTANCE, -mge->dDist * 10.f); GameCameraRotate(game, -mge->dTheta * 100.0f); //GLOUTPUT(("MultiGestureEvent dTheta=%.4f dDist=%.4f x=%.4f y=%.4f nFing=%d\n", mge->dTheta, mge->dDist, mge->x, mge->y, mge->numFingers)); } } break; case SDL_DOLLARGESTURE: { GLOUTPUT(("DollarGestureEvent\n")); } break; case SDL_QUIT: { done = true; } break; default: break; } } U32 delta = SDL_GetTicks() - tickTimer; if (delta < TIME_BETWEEN_FRAMES) { SDL_Delay(1); continue; } tickTimer = SDL_GetTicks(); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); const U8* keys = SDL_GetKeyboardState(0); U32 tickDelta = thisTick - lastTick; if (tickDelta > 100) tickDelta = 100; float keyMoveSpeed = KEY_MOVE_SPEED * float(tickDelta) / float(TIME_BETWEEN_FRAMES); float keyZoomSpeed = KEY_ZOOM_SPEED * float(tickDelta) / float(TIME_BETWEEN_FRAMES); float keyRotatepeed = KEY_ROTATE_SPEED * float(tickDelta) / float(TIME_BETWEEN_FRAMES); if (keys[SDL_SCANCODE_DOWN] || keys[SDL_SCANCODE_S]) { if (modKeys & KMOD_CTRL) GameZoom(game, GAME_ZOOM_DISTANCE, keyZoomSpeed); else GameCameraMove(game, 0, -keyMoveSpeed); } if (keys[SDL_SCANCODE_UP] || keys[SDL_SCANCODE_W]) { if (modKeys & KMOD_CTRL) GameZoom(game, GAME_ZOOM_DISTANCE, -keyZoomSpeed); else GameCameraMove(game, 0, keyMoveSpeed); } if (keys[SDL_SCANCODE_LEFT] || keys[SDL_SCANCODE_A]) { if (modKeys & KMOD_CTRL) GameCameraRotate(game, keyRotatepeed); else GameCameraMove(game, -keyMoveSpeed, 0); } if (keys[SDL_SCANCODE_RIGHT] || keys[SDL_SCANCODE_D]) { if (modKeys & KMOD_CTRL) GameCameraRotate(game, -keyRotatepeed); else GameCameraMove(game, keyMoveSpeed, 0); } if (game) { lastTick = thisTick; thisTick = SDL_GetTicks(); PROFILE_BLOCK(GameDoTick); GameDoTick(game, thisTick); } { PROFILE_BLOCK(Swap); SDL_GL_SwapWindow(screen); } } GameSave(game); DeleteGame(game); for (int i = 0; i < nModDB; ++i) { delete databases[i]; } SDL_Quit(); #if SEND_CRASH_LOGS // Empty the file - quit went just fine. { FILE* fp = FOpen( "UFO_Running.txt", "w" ); if ( fp ) fclose( fp ); } #endif MemLeakCheck(); return 0; }
bool LastingEffects::tick(Creature* c, LastingEffect effect) { PROFILE_BLOCK("LastingEffects::tick"); switch (effect) { case LastingEffect::BLEEDING: c->getBody().bleed(c, 0.03); c->secondPerson(PlayerMessage("You are bleeding.", MessagePriority::HIGH)); c->thirdPerson(PlayerMessage(c->getName().the() + " is bleeding.", MessagePriority::HIGH)); if (c->getBody().getHealth() <= 0) { c->you(MsgType::DIE_OF, "bleeding"); c->dieWithLastAttacker(); return true; } break; case LastingEffect::REGENERATION: c->getBody().heal(c, 0.03); break; case LastingEffect::ON_FIRE: c->getPosition().fireDamage(0.1); break; case LastingEffect::POISON: c->getBody().bleed(c, 0.03); c->secondPerson(PlayerMessage("You suffer from poisoning.", MessagePriority::HIGH)); c->thirdPerson(PlayerMessage(c->getName().the() + " suffers from poisoning.", MessagePriority::HIGH)); if (c->getBody().getHealth() <= 0) { c->you(MsgType::DIE_OF, "poisoning"); c->dieWithLastAttacker(); return true; } break; case LastingEffect::WARNING: { const int radius = 5; bool isDanger = false; bool isBigDanger = false; auto position = c->getPosition(); for (Position v : position.getRectangle(Rectangle(-radius, -radius, radius + 1, radius + 1))) { for (auto f : v.getFurniture()) if (f->emitsWarning(c)) { if (v.dist8(position).value_or(2) <= 1) isBigDanger = true; else isDanger = true; } if (Creature* enemy = v.getCreature()) { if (!c->canSee(enemy) && c->isEnemy(enemy)) { int diff = enemy->getAttr(AttrType::DAMAGE) - c->getAttr(AttrType::DEFENSE); if (diff > 5) isBigDanger = true; else if (diff > 0) isDanger = true; } } } if (isBigDanger) c->privateMessage(PlayerMessage("You sense big danger!", MessagePriority::HIGH)); else if (isDanger) c->privateMessage(PlayerMessage("You sense danger!", MessagePriority::HIGH)); break; } case LastingEffect::SUNLIGHT_VULNERABLE: if (c->getPosition().sunlightBurns()) { c->you(MsgType::ARE, "burnt by the sun"); if (Random.roll(10)) { c->you(MsgType::YOUR, "body crumbles to dust"); c->dieWithReason("killed by sunlight", Creature::DropType::ONLY_INVENTORY); return true; } } break; case LastingEffect::ENTERTAINER: if (!c->isAffected(LastingEffect::SLEEP) && Random.roll(50)) { auto others = c->getVisibleCreatures().filter([](const Creature* c) { return c->getBody().hasBrain() && c->getBody().isHumanoid(); }); if (others.empty()) break; string jokeText = "a joke"; optional<LastingEffect> hatedGroup; for (auto effect : getHateEffects()) if (c->isAffected(effect) || (c->getAttributes().getHatedByEffect() != effect && Random.roll(10 * getHateEffects().size()))) { hatedGroup = effect; break; } if (hatedGroup) jokeText.append(" about "_s + getHatedGroupName(*hatedGroup)); c->verb("crack", "cracks", jokeText); for (auto other : others) if (other != c && !other->isAffected(LastingEffect::SLEEP)) { if (hatedGroup && hatedGroup == other->getAttributes().getHatedByEffect()) { other->addMorale(-0.05); other->you(MsgType::ARE, "offended"); } else { other->verb("laugh", "laughs"); other->addMorale(0.01); } } } break; case LastingEffect::BAD_BREATH: for (auto pos : c->getPosition().getRectangle(Rectangle::centered(7))) if (auto other = pos.getCreature()) other->addMorale(-0.002); break; case LastingEffect::DISAPPEAR_DURING_DAY: if (c->getGame()->getSunlightInfo().getState() == SunlightState::DAY) c->dieNoReason(Creature::DropType::ONLY_INVENTORY); break; default: break; } return false; }
void updateAsyncTransactions() override { PROFILE_FUNCTION(); while (!m_in_progress.empty()) { AsynTrans* tr = m_in_progress.front(); if (!tr->isCompleted()) break; PROFILE_BLOCK("processAsyncTransaction"); m_in_progress.pop(); if ((tr->data.m_flags & E_CANCELED) == 0) { tr->data.m_cb.invoke(*tr->data.m_file, !!(tr->data.m_flags & E_SUCCESS)); } if ((tr->data.m_flags & (E_SUCCESS | E_FAIL)) != 0) { closeAsync(*tr->data.m_file); } m_transaction_queue.dealoc(tr); } i32 can_add = C_MAX_TRANS - m_in_progress.size(); while (can_add && !m_pending.empty()) { AsynTrans* tr = m_transaction_queue.alloc(false); if (tr) { AsyncItem& item = m_pending[0]; tr->data.m_file = item.m_file; tr->data.m_cb = item.m_cb; tr->data.m_id = item.m_id; tr->data.m_mode = item.m_mode; copyString(tr->data.m_path, sizeof(tr->data.m_path), item.m_path); tr->data.m_flags = item.m_flags; tr->reset(); m_transaction_queue.push(tr, true); m_in_progress.push(tr); m_pending.erase(0); } can_add--; } #if LUMIX_SINGLE_THREAD() while (AsynTrans* tr = m_transaction_queue.pop(false)) { PROFILE_BLOCK("transaction"); if ((tr->data.m_flags & E_IS_OPEN) == E_IS_OPEN) { tr->data.m_flags |= tr->data.m_file->open(Path(tr->data.m_path), tr->data.m_mode) ? E_SUCCESS : E_FAIL; } else if ((tr->data.m_flags & E_CLOSE) == E_CLOSE) { tr->data.m_file->close(); tr->data.m_file->release(); tr->data.m_file = nullptr; } tr->setCompleted(); } #endif }