Skip to content

Commit 8bed6ba

Browse files
committed
feat: 添加调试器功能,支持多次调用和等待命令,更新版本号至8.2.123
1 parent e6c7d85 commit 8bed6ba

File tree

12 files changed

+713
-21
lines changed

12 files changed

+713
-21
lines changed

source/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ find_package(fmt REQUIRED)
9898
find_package(imgui REQUIRED)
9999
find_package(OpenCV REQUIRED)
100100
find_package(cereal REQUIRED)
101+
target_include_directories(cvAutoTrack PRIVATE ${OpenCV_INCLUDE_DIRS})
101102
target_link_libraries(cvAutoTrack
102103
PRIVATE
103104
tianli::frame
@@ -107,7 +108,6 @@ PRIVATE
107108
imgui::imgui
108109
opengl32
109110
)
110-
target_include_directories(cvAutoTrack PRIVATE ${OpenCV_INCLUDE_DIRS})
111111

112112
add_custom_target(copy_version_file ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/resource/version.ver" "$<TARGET_FILE_DIR:cvAutoTrack>/version")
113113
set_target_properties(copy_version_file PROPERTIES FOLDER "scripts")

source/cvAutoTrack.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,20 @@ cvAutoTrackContextV2* create_cvAutoTrack_context_v2()
271271
gui->destory();
272272
}
273273
}
274+
else if (args == "wait")
275+
{
276+
if (auto gui = global::shareder<debugger>::get(); gui)
277+
{
278+
gui->wait_exit();
279+
}
280+
}
281+
}
282+
else
283+
{
284+
if (auto gui = global::shareder<debugger>::get(); gui)
285+
{
286+
gui->call(cmd, args);
287+
}
274288
}
275289
return true;
276290
};

source/global/debugger.cpp

Lines changed: 187 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,69 @@ void window_opengl::shutdown()
118118
::UnregisterClassW(wc.lpszClassName, wc.hInstance);
119119
}
120120

121+
#include "one_call_function.hpp"
121122
#include "single_async_executor.hpp"
123+
#include "syncer.hpp"
122124
#include <atomic>
123125
#include <iostream>
126+
127+
#include <mutex>
128+
129+
struct async_ogl
130+
{
131+
HWND hwnd;
132+
HDC hdc;
133+
HGLRC hglrc;
134+
std::mutex mutex;
135+
void init(HWND hwnd, HGLRC main_hglrc)
136+
{
137+
this->hwnd = hwnd;
138+
hdc = ::GetDC(hwnd);
139+
hglrc = wglCreateContext(hdc);
140+
if (main_hglrc)
141+
wglShareLists(main_hglrc, hglrc);
142+
}
143+
void destory(HWND hwnd)
144+
{
145+
std::unique_lock lock(mutex);
146+
if (hglrc)
147+
{
148+
wglMakeCurrent(hdc, nullptr);
149+
wglDeleteContext(hglrc);
150+
hglrc = nullptr;
151+
}
152+
if (hdc)
153+
{
154+
ReleaseDC(hwnd, hdc);
155+
hdc = nullptr;
156+
}
157+
}
158+
};
159+
160+
struct unique_ogl_lock
161+
{
162+
async_ogl& async;
163+
bool ret = {};
164+
unique_ogl_lock(async_ogl& async) : async(async)
165+
{
166+
async.mutex.lock();
167+
ret = wglMakeCurrent(async.hdc, async.hglrc);
168+
}
169+
~unique_ogl_lock()
170+
{
171+
wglMakeCurrent(async.hdc, nullptr);
172+
wglMakeCurrent(nullptr, nullptr);
173+
async.mutex.unlock();
174+
}
175+
};
176+
124177
struct imapp
125178
{
126179
window_opengl window;
180+
stdex::one_call_function<void()> one_call;
127181
stdex::single_async_executor<void> executor;
182+
stdex::syncer<std::function<void()>, true> render_syncer;
183+
std::function<void()> render;
128184
std::atomic_flag is_running = ATOMIC_FLAG_INIT;
129185

130186
void async_execute()
@@ -135,28 +191,48 @@ struct imapp
135191
create();
136192
while (is_running.test_and_set())
137193
{
194+
one_call();
195+
138196
event_process();
139197
new_frame();
140-
render();
198+
199+
render_syncer.try_sync(render);
200+
if (render)
201+
render();
202+
203+
render_and_swap();
141204
}
142205
destory();
143206
}
144207
catch (const std::exception& e)
145208
{
146-
std::cerr << "Exception: " << e.what() << std::endl;
209+
// std::cerr << "Exception: " << e.what() << std::endl;
147210
}
148211
catch (...)
149212
{
150-
std::cerr << "Unknown exception occurred." << std::endl;
213+
// std::cerr << "Unknown exception occurred." << std::endl;
151214
}
152215
});
153216
}
154217

155218
void create();
156219
void event_process();
157220
void new_frame();
158-
void render();
221+
void render_and_swap();
159222
void destory();
223+
224+
std::shared_ptr<async_ogl> create_async_ogl()
225+
{
226+
auto async = std::make_shared<async_ogl>();
227+
std::promise<void> promise;
228+
std::future<void> future = promise.get_future();
229+
one_call = [&promise = std::move(promise), async, this]() {
230+
async->init(window.hwnd, window.hglrc);
231+
promise.set_value();
232+
};
233+
future.wait();
234+
return async;
235+
}
160236
};
161237
void imapp::create()
162238
{
@@ -166,6 +242,7 @@ void imapp::create()
166242
IMGUI_CHECKVERSION();
167243
ImGui::CreateContext();
168244
ImGuiIO& io = ImGui::GetIO();
245+
io.IniFilename = nullptr; // Disable .ini file
169246
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
170247
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
171248

@@ -187,18 +264,23 @@ void imapp::event_process()
187264
::TranslateMessage(&msg);
188265
::DispatchMessage(&msg);
189266
if (msg.message == WM_QUIT)
190-
is_running.clear();
267+
{
268+
std::cout << "Quit message received." << std::endl;
269+
// is_running.clear();
270+
}
191271
}
192272
if (::IsIconic(window.hwnd))
193273
::Sleep(10);
274+
if (::IsWindow(window.hwnd) == false)
275+
is_running.clear();
194276
}
195277
void imapp::new_frame()
196278
{
197279
ImGui_ImplOpenGL3_NewFrame();
198280
ImGui_ImplWin32_NewFrame();
199281
ImGui::NewFrame();
200282
}
201-
void imapp::render()
283+
void imapp::render_and_swap()
202284
{
203285
ImGui::Render();
204286
glViewport(0, 0, window.width, window.height);
@@ -216,30 +298,127 @@ void imapp::destory()
216298
window.shutdown();
217299
}
218300

301+
#include <opencv2/core/opengl.hpp>
302+
219303
struct debugger::impl_t
220304
{
221305
imapp app;
306+
std::vector<unique_render_image> render_images;
307+
stdex::syncer<std::vector<unique_render_image>, true> render_image_syncer;
222308

223309
void setup() { app.async_execute(); }
224310
void shutdown()
225311
{
226312
app.is_running.clear();
227-
app.executor.wait();
313+
wait_exit();
228314
}
315+
void wait_exit() { app.executor.wait(); }
316+
void update_render(std::function<void()> render) { app.render_syncer.set(render); }
229317
};
230318

231319
debugger::debugger() : impl(std::make_unique<impl_t>()) {}
232-
debugger::~debugger() { impl->shutdown(); }
320+
debugger::~debugger()
321+
{
322+
impl->shutdown();
323+
}
324+
#include "pool.hpp"
233325

234326
void debugger::initlize()
235327
{
236328
impl->setup();
329+
330+
set_render([this]() {
331+
ImGui::Begin("Debugger");
332+
ImGui::Text("Render Images");
333+
ImGui::Text("Press 'R' to refresh");
334+
if (ImGui::Button("Refresh"))
335+
{
336+
static stdex::single_async_executor<void> async_executor;
337+
async_executor.submit_exclusive([this]() {
338+
auto ogl = impl->app.create_async_ogl();
339+
unique_ogl_lock lock(*ogl);
340+
341+
std::vector<unique_render_image> images;
342+
for (int i = 0; i < 1; ++i)
343+
{
344+
cv::Mat image = cv::Mat::zeros(200, 200, CV_8UC3);
345+
cv::rectangle(image, cv::Point(rand() % 50 + 2, 50), cv::Point(150, 150), cv::Scalar(0, 255, 0), -1);
346+
unique_render_image render_image;
347+
render_image.tex_ref = std::make_shared<cv::ogl::Texture2D>(image, true);
348+
render_image.texture_id = render_image.tex_ref->texId();
349+
render_image.width = image.cols;
350+
render_image.height = image.rows;
351+
images.push_back(render_image);
352+
}
353+
impl->render_image_syncer.set(images);
354+
});
355+
}
356+
impl->render_image_syncer.try_sync(impl->render_images);
357+
for (auto& image : impl->render_images)
358+
{
359+
ImGui::Image((intptr_t)image.texture_id, ImVec2(image.width, image.height));
360+
}
361+
ImGui::End();
362+
});
237363
}
238364
void debugger::destory()
239365
{
240366
impl->shutdown();
241367
}
368+
void debugger::wait_exit()
369+
{
370+
impl->wait_exit();
371+
}
372+
void debugger::set_render(std::function<void()> render)
373+
{
374+
impl->update_render(render);
375+
}
376+
// #include "self_releasing_async.hpp"
377+
378+
#include <frame/frame.include.h>
379+
#include <global/record/record.stdlog.h>
242380
std::string debugger::call(std::string command, std::string args)
243381
{
382+
if (command == "capture")
383+
{
384+
if (args == "current")
385+
{
386+
387+
auto logger = std::make_shared<tianli::global::record::std_logger>();
388+
auto capture = tianli::frame::frame_source::create(tianli::frame::frame_source::source_type::bitblt, logger);
389+
cv::Mat frame;
390+
391+
capture->set_capture_handle(GetDesktopWindow());
392+
while (frame.empty())
393+
{
394+
std::this_thread::sleep_for(std::chrono::milliseconds(18));
395+
capture->get_frame(frame);
396+
std::cout << "Capture current frame" << std::endl;
397+
if (frame.empty())
398+
{
399+
std::cout << "Capture failed" << std::endl;
400+
}
401+
}
402+
static stdex::single_async_executor<void> async_executor;
403+
async_executor.submit_exclusive([frame, this]() {
404+
auto ogl = impl->app.create_async_ogl();
405+
unique_ogl_lock lock(*ogl);
406+
std::vector<unique_render_image> images;
407+
{
408+
unique_render_image render_image;
409+
render_image.tex_ref = std::make_shared<cv::ogl::Texture2D>(frame.clone(), true);
410+
render_image.texture_id = render_image.tex_ref->texId();
411+
render_image.width = render_image.tex_ref->cols();
412+
render_image.height = render_image.tex_ref->rows();
413+
images.push_back(render_image);
414+
}
415+
impl->render_image_syncer.set(images);
416+
});
417+
}
418+
}
419+
else
420+
{
421+
return "Unknown command";
422+
}
244423
return {};
245424
}

source/global/debugger.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
#pragma once
22
#include <memory>
33
#include <string>
4+
5+
#include <opencv2/core/opengl.hpp>
6+
7+
struct unique_render_image
8+
{
9+
int texture_id;
10+
int width;
11+
int height;
12+
std::shared_ptr<cv::ogl::Texture2D> tex_ref;
13+
};
14+
415
struct debugger
516
{
617
struct impl_t;
@@ -10,5 +21,7 @@ struct debugger
1021

1122
void initlize();
1223
void destory();
24+
void wait_exit();
25+
void set_render(std::function<void()> render);
1326
std::string call(std::string command, std::string args);
14-
};
27+
};

source/global/global.include.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ namespace tianli::global
6868
return index;
6969
}
7070

71-
#define error(msg) \
71+
#define errreg(msg) \
7272
tianli::global::error_proxy<tianli::global::error_invoker, tianli::global::source_location(__FILE__, std::source_location::current().line(), std::source_location::current().column()), \
7373
tianli::global::error_message(msg)>::callback(tianli::global::error_impl, msg)
7474
#else
75-
#define error(msg)
75+
#define errreg(msg)
7676
#endif
7777

7878
class error_type

0 commit comments

Comments
 (0)