Lib
QOLを高める
framework.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 #include "include/framework.h"
3 #include "include/debug.h"
4 #include "include/exceptions.h"
5 #include <random>
6 
7 namespace yappy {
8 namespace framework {
9 
11 
12 namespace random {
13 
14 namespace {
15 std::random_device s_randomDevice;
16 std::mt19937 s_mt;
17 } // namespace
18 
19 unsigned int generateRandomSeed()
20 {
21  return s_randomDevice();
22 }
23 
24 void setSeed(unsigned int seed)
25 {
26  s_mt.seed(seed);
27 }
28 
29 unsigned int nextRawUInt32()
30 {
31  return s_mt();
32 }
33 
34 int nextInt(int a, int b)
35 {
36  std::uniform_int_distribution<int> dist(a, b);
37  return dist(s_mt);
38 }
39 
40 double nextDouble(double a, double b)
41 {
42  std::uniform_real_distribution<double> dist(a, b);
43  return dist(s_mt);
44 }
45 
46 } // namespace random
47 
48 namespace scene {
49 
51 // class AsyncLoadScene impl
53 #pragma region AsyncLoadScene
54 
55 AsyncLoadScene::~AsyncLoadScene()
56 {
57  // set cancel flag
58  m_cancel.store(true);
59  // m_future destructor will wait for sub thread
60 }
61 
62 void AsyncLoadScene::update()
63 {
64  updateLoadStatus();
65  updateOnMainThread();
66 }
67 
68 void AsyncLoadScene::startLoadThread()
69 {
70  if (m_future.valid()) {
71  throwTrace<std::logic_error>("Async task is already running");
72  }
73  // move assign
74  m_future = std::async(std::launch::async, [this]() {
75  // can throw an exception
76  loadOnSubThread(m_cancel);
77  });
78 }
79 
80 void AsyncLoadScene::updateLoadStatus()
81 {
82  if (m_future.valid()) {
83  auto status = m_future.wait_for(std::chrono::seconds(0));
84  switch (status) {
85  case std::future_status::ready:
86  // complete or exception
87  // make m_future invalid
88  // if an exception is thrown in sub thread, throw it
89  m_future.get();
90  break;
91  case std::future_status::timeout:
92  // not yet
93  break;
94  default:
95  ASSERT(false);
96  }
97  }
98 }
99 
100 bool AsyncLoadScene::isLoading() const
101 {
102  return m_future.valid();
103 }
104 
105 } // namespace scene
106 
107 #pragma endregion
108 
109 std::vector<std::wstring> parseCommandLine()
110 {
111  // get as const pointer
112  const WCHAR *cmdline = ::GetCommandLineW();
113 
114  // covert to argc, argv
115  // "quoted string including spaces" will be resolved
116  int argc = -1;
117  WCHAR **tmpArgv = ::CommandLineToArgvW(cmdline, &argc);
118  checkWin32Result(tmpArgv != nullptr, "CommandLineToArgvW() failed");
119  // use unique_ptr<T[]> for operator []
120  // LocalFree() instead of delete[]
121  auto del = [](WCHAR **ptr) {
122  ::LocalFree(ptr);
123  };
124  std::unique_ptr<WCHAR *[], decltype(del)> argv(tmpArgv, del);
125 
126  std::vector<std::wstring> result(&argv[0], &argv[argc]);
127  return result;
128 }
129 
131 // class ResourceManager impl
133 #pragma region ResourceManager
134 
135 ResourceManager::ResourceManager(size_t resSetCount) :
136  m_texMapVec(resSetCount),
137  m_fontMapVec(resSetCount),
138  m_seMapVec(resSetCount),
139  m_bgmMapVec(resSetCount)
140 {}
141 
142 namespace {
143 
144 template <class T, class U>
145 void addResource(ResourceManager::ResMapVec<T> *targetMapVec, bool locked,
146  size_t setId, const char * resId, std::function<U> loadFunc)
147 {
148  if (locked) {
149  throwTrace<std::logic_error>("Resource is not allowed to be added now");
150  }
151 
152  IdString fixedResId;
153  util::createFixedString(&fixedResId, resId);
154  std::unordered_map<IdString, Resource<T>> &map =
155  targetMapVec->at(setId);
156  if (map.count(fixedResId) != 0) {
157  throwTrace<std::invalid_argument>(std::string("Resource ID already exists: ") + resId);
158  }
159  // key = IdString(fixedResId)
160  // value = Resource<T>(loadfunc)
161  map.emplace(std::piecewise_construct,
162  std::forward_as_tuple(fixedResId),
163  std::forward_as_tuple(loadFunc));
164 }
165 
166 } // namespace
167 
168 void ResourceManager::addTexture(size_t setId, const char * resId,
169  std::function<graphics::DGraphics::TextureResourcePtr()> loadFunc)
170 {
171  addResource(&m_texMapVec, m_sealed, setId, resId, loadFunc);
172 }
173 
174 void ResourceManager::addFont(size_t setId, const char *resId,
175  std::function<graphics::DGraphics::FontResourcePtr()> loadFunc)
176 {
177  addResource(&m_fontMapVec, m_sealed, setId, resId, loadFunc);
178 }
179 
180 void ResourceManager::addSoundEffect(size_t setId, const char *resId,
181  std::function<sound::XAudio2::SeResourcePtr()> loadFunc)
182 {
183  addResource(&m_seMapVec, m_sealed, setId, resId, loadFunc);
184 }
185 
186 void ResourceManager::addBgm(size_t setId, const char *resId,
187  std::function<sound::XAudio2::BgmResourcePtr()> loadFunc)
188 {
189  addResource(&m_bgmMapVec, m_sealed, setId, resId, loadFunc);
190 }
191 
193 {
194  m_sealed = seal;
195 }
196 
198 {
199  return m_sealed;
200 }
201 
202 namespace {
203 
204 template <class T>
205 void loadAll(ResourceManager::ResMapVec<T> *targetMapVec, size_t setId, std::atomic_bool &cancel)
206 {
207  for (auto &elem : targetMapVec->at(setId)) {
208  if (cancel.load()) {
209  break;
210  }
211  elem.second.load();
212  }
213 }
214 
215 template <class T>
216 void unloadAll(ResourceManager::ResMapVec<T> *targetMapVec, size_t setId)
217 {
218  for (auto &elem : targetMapVec->at(setId)) {
219  elem.second.unload();
220  }
221 }
222 
223 } // namespace
224 
225 void ResourceManager::loadResourceSet(size_t setId, std::atomic_bool &cancel)
226 {
227  loadAll(&m_texMapVec, setId, cancel);
228  loadAll(&m_fontMapVec, setId, cancel);
229  loadAll(&m_seMapVec, setId, cancel);
230  loadAll(&m_bgmMapVec, setId, cancel);
231 }
232 
234 {
235  unloadAll(&m_texMapVec, setId);
236  unloadAll(&m_fontMapVec, setId);
237  unloadAll(&m_seMapVec, setId);
238  unloadAll(&m_bgmMapVec, setId);
239 }
240 
241 namespace {
242 
243 template <class T>
244 const typename Resource<T>::PtrType getResource(
245  const std::vector<std::unordered_map<IdString, Resource<T>>> &mapVec,
246  size_t setId, const char *resId)
247 {
248  IdString fixedResId;
249  util::createFixedString(&fixedResId, resId);
250  auto &map = mapVec.at(setId);
251  if (map.count(fixedResId) == 0) {
252  throwTrace<std::invalid_argument>(std::string("Resource ID not found: ") + resId);
253  }
254  return map.at(fixedResId).getPtr();
255 }
256 
257 }
258 
260  size_t setId, const char *resId) const
261 {
262  return getResource(m_texMapVec, setId, resId);
263 }
264 
266  size_t setId, const char *resId) const
267 {
268  return getResource(m_fontMapVec, setId, resId);
269 }
270 
272  size_t setId, const char *resId) const
273 {
274  return getResource(m_seMapVec, setId, resId);
275 }
276 
278  size_t setId, const char *resId) const
279 {
280  return getResource(m_bgmMapVec, setId, resId);
281 }
282 
283 #pragma endregion
284 
286 // class FrameControl impl
288 #pragma region FrameControl
289 
290 namespace {
291 
292 inline int64_t getTimeCounter()
293 {
294  LARGE_INTEGER cur;
295  BOOL b = ::QueryPerformanceCounter(&cur);
296  checkWin32Result(b != 0, "QueryPerformanceCounter() failed");
297  return cur.QuadPart;
298 }
299 
300 } // namespace
301 
302 FrameControl::FrameControl(uint32_t fps, uint32_t skipCount) :
303  m_skipCount(skipCount),
304  m_fpsPeriod(fps)
305 {
306  // counter/sec
307  LARGE_INTEGER freq;
308  BOOL b = ::QueryPerformanceFrequency(&freq);
309  checkWin32Result(b != FALSE, "QueryPerformanceFrequency() failed");
310  m_freq = freq.QuadPart;
311 
312  // counter/frame = (counter/sec) / (frame/sec)
313  // = m_freq / fps
314  m_counterPerFrame = m_freq / fps;
315 }
316 
318 {
319  return m_frameCount != 0;
320 }
321 
323 {
324  // for fps calc
325  if (!shouldSkipFrame()) {
326  m_fpsFrameAcc++;
327  }
328 
329  int64_t target = m_base + m_counterPerFrame;
330  int64_t cur = getTimeCounter();
331  if (m_base == 0) {
332  // force OK
333  m_base = cur;
334  }
335  else if (cur < target) {
336  // OK, wait for next frame
337  while (cur < target) {
338  ::Sleep(1);
339  cur = getTimeCounter();
340  }
341  // may overrun a little bit, add it to next frame
342  m_base = target;
343  }
344  else {
345  // too late, probably immediately right after vsync
346  m_base = cur;
347  }
348 
349  // m_frameCount++;
350  // m_frameCount %= (#draw(=1) + #skip)
351  m_frameCount = (m_frameCount + 1) % (1 + m_skipCount);
352 
353  // for fps calc
354  m_fpsCount++;
355  if (m_fpsCount >= m_fpsPeriod) {
356  double sec = static_cast<double>(cur - m_fpsBase) / m_freq;
357  m_fps = m_fpsFrameAcc / sec;
358 
359  m_fpsCount = 0;
360  m_fpsFrameAcc = 0;
361  m_fpsBase = cur;
362  }
363 }
364 
366 {
367  return m_fps;
368 }
369 
370 #pragma endregion
371 
373 // class Application impl
375 #pragma region Application
376 
378  const graphics::GraphicsParam &graphParam,
379  size_t resSetCount) :
380  m_hWnd(nullptr),
381  m_resMgr(resSetCount),
382  m_param(appParam),
383  m_graphParam(graphParam),
384  m_frameCtrl(graphParam.refreshRate, appParam.frameSkip)
385 {
386  // window
387  initializeWindow();
388  m_graphParam.hWnd = m_hWnd;
389 
390  // DirectGraphics
391  auto *tmpDg = new graphics::DGraphics(m_graphParam);
392  m_dg.reset(tmpDg);
393  // XAudio2
394  auto *tmpXa2 = new sound::XAudio2();
395  m_ds.reset(tmpXa2);
396  // DirectInput
397  auto *tmpDi = new input::DInput(m_param.hInstance, m_hWnd);
398  m_di.reset(tmpDi);
399 }
400 
401 void Application::initializeWindow()
402 {
403  debug::writeLine(L"Initializing window...");
404 
405  // Register class
406  WNDCLASSEX cls = { 0 };
407  cls.cbSize = sizeof(WNDCLASSEX);
408  cls.style = 0;
409  cls.lpfnWndProc = wndProc;
410  cls.cbClsExtra = 0;
411  cls.cbWndExtra = 0;
412  cls.hInstance = m_param.hInstance;
413  cls.hIcon = m_param.hIcon;
414  cls.hCursor = LoadCursor(NULL, IDC_ARROW);
415  cls.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BTNFACE + 1);
416  cls.lpszMenuName = nullptr;
417  cls.lpszClassName = m_param.wndClsName;
418  cls.hIconSm = m_param.hIconSm;
419  checkWin32Result(::RegisterClassEx(&cls) != 0, "RegisterClassEx() failed");
420 
421  const DWORD wndStyle = WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX;
422 
423  RECT rc = { 0, 0, m_graphParam.w, m_graphParam.h };
424  checkWin32Result(::AdjustWindowRect(&rc, wndStyle, FALSE) != FALSE,
425  "AdjustWindowRect() failed");
426 
427  m_hWnd = ::CreateWindow(m_param.wndClsName, m_param.title, wndStyle,
428  CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,
429  nullptr, nullptr, m_param.hInstance, this);
430  checkWin32Result(m_hWnd != nullptr, "CreateWindow() failed");
431 
432  // for frame processing while window drugging etc.
433  ::SetTimer(m_hWnd, TimerEventId, 1, nullptr);
434 
435  // Show cursor
436  if (m_param.showCursor) {
437  while (::ShowCursor(TRUE) < 0);
438  }
439  else {
440  while (::ShowCursor(FALSE) >= 0);
441  }
442 
443  debug::writeLine(L"Initializing window OK");
444 }
445 
447 {
448  debug::writeLine(L"Finalize Application Window");
449  if (m_hWnd != nullptr) {
450  ::DestroyWindow(m_hWnd);
451  m_hWnd = nullptr;
452  }
453 }
454 
455 LRESULT CALLBACK Application::wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
456 {
457  if (msg == WM_CREATE) {
458  // Associate this ptr with hWnd
459  void *userData = reinterpret_cast<LPCREATESTRUCT>(lParam)->lpCreateParams;
460  ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(userData));
461  }
462 
463  LONG_PTR user = ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
464  Application *self = reinterpret_cast<Application *>(user);
465 
466  switch (msg) {
467  case WM_TIMER:
468  self->onIdle();
469  return 0;
470  case WM_SIZE:
471  return self->onSize(hWnd, msg, wParam, lParam);
472  case WM_DESTROY:
473  self->m_hWnd = nullptr;
474  PostQuitMessage(0);
475  return 0;
476  }
477  return ::DefWindowProc(hWnd, msg, wParam, lParam);
478 }
479 
480 LRESULT Application::onSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
481 {
482  return m_dg->onSize(hWnd, msg, wParam, lParam);
483 }
484 
485 // main work
486 // update(), then draw() if FrameControl allowed
487 void Application::onIdle()
488 {
489  updateInternal();
490  if (!m_frameCtrl.shouldSkipFrame()) {
491  renderInternal();
492  }
493  m_frameCtrl.endFrame();
494 
495  // fps
496  wchar_t buf[256] = { 0 };
497  swprintf_s(buf, L"%s fps=%.2f (%d)", m_param.title,
498  m_frameCtrl.getFramePerSec(), m_param.frameSkip);
499  ::SetWindowText(m_hWnd, buf);
500 }
501 
502 void Application::updateInternal()
503 {
504  m_ds->processFrame();
505  m_di->processFrame();
506  // Call user code
507  update();
508 }
509 
510 void Application::renderInternal()
511 {
512  // TEST: frame skip
513  /*
514  uint32_t skip = 3;
515  ::Sleep(17 * skip);
516  //*/
517 
518  // Call user code
519  render();
520 
521  m_dg->render();
522 }
523 
525 {
526  // Call user code
527  init();
528 
529  ::ShowWindow(m_hWnd, m_param.nCmdShow);
530  ::UpdateWindow(m_hWnd);
531 
532  MSG msg = { 0 };
533  while (msg.message != WM_QUIT) {
534  if (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
535  ::TranslateMessage(&msg);
536  ::DispatchMessage(&msg);
537  }
538  else {
539  // main work
540  onIdle();
541  }
542  }
543  return static_cast<int>(msg.wParam);
544 }
545 
546 
547 void Application::addTextureResource(size_t setId, const char *resId, const wchar_t *path)
548 {
549  std::wstring pathCopy(path);
550  m_resMgr.addTexture(setId, resId, [this, pathCopy]() {
551  yappy::debug::writef(L"LoadTexture: %s", pathCopy.c_str());
552  return m_dg->loadTexture(pathCopy.c_str());
553  });
554 }
555 
556 void Application::addFontResource(size_t setId, const char *resId,
557  const wchar_t *fontName, uint32_t startChar, uint32_t endChar,
558  uint32_t w, uint32_t h)
559 {
560  std::wstring fontNameCopy(fontName);
561  m_resMgr.addFont(setId, resId, [this, fontNameCopy, startChar, endChar, w, h]() {
562  yappy::debug::writef(L"CreateFont: %s", fontNameCopy.c_str());
563  return m_dg->loadFont(fontNameCopy.c_str(), startChar, endChar, w, h);
564  });
565 }
566 
567 void Application::addSeResource(size_t setId, const char *resId, const wchar_t *path)
568 {
569  std::wstring pathCopy(path);
570  m_resMgr.addSoundEffect(setId, resId, [this, pathCopy]() {
571  yappy::debug::writef(L"LoadSoundEffect: %s", pathCopy.c_str());
572  return m_ds->loadSoundEffect(pathCopy.c_str());
573  });
574 }
575 
576 void Application::addBgmResource(size_t setId, const char *resId, const wchar_t *path)
577 {
578  std::wstring pathCopy(path);
579  m_resMgr.addBgm(setId, resId, [this, pathCopy]() {
580  yappy::debug::writef(L"LoadBgm: %s", pathCopy.c_str());
581  return m_ds->loadBgm(pathCopy.c_str());
582  });
583 }
584 
586 {
587  m_resMgr.setSealed(seal);
588 }
589 
590 void Application::loadResourceSet(size_t setId, std::atomic_bool &cancel)
591 {
592  m_resMgr.loadResourceSet(setId, cancel);
593 }
595 {
596  m_resMgr.unloadResourceSet(setId);
597 }
598 
600  size_t setId, const char *resId) const
601 {
602  return m_resMgr.getTexture(setId, resId);
603 }
604 
606  size_t setId, const char *resId) const
607 {
608  return m_resMgr.getFont(setId, resId);
609 }
610 
612  size_t setId, const char *resId) const
613 {
614  return m_resMgr.getSoundEffect(setId, resId);
615 }
616 
618  size_t setId, const char *resId) const
619 {
620  return m_resMgr.getBgm(setId, resId);
621 }
622 
623 #pragma endregion
624 
625 } // namespace framework
626 } // namespace yappy
HINSTANCE hInstance
hInstance from WinMain.
Definition: framework.h:280
int run()
Start main loop.
Definition: framework.cpp:524
void addTextureResource(size_t setId, const char *resId, const wchar_t *path)
Register texture image resource.
Definition: framework.cpp:547
HICON hIcon
hIcon for window class.
Definition: framework.h:288
void addFontResource(size_t setId, const char *resId, const wchar_t *fontName, uint32_t startChar, uint32_t endChar, uint32_t w, uint32_t h)
Register font image resource.
Definition: framework.cpp:556
const sound::XAudio2::SeResourcePtr getSoundEffect(size_t setId, const char *resId) const
Definition: framework.cpp:271
int nextInt(int a, int b)
Get next int random number.
Definition: framework.cpp:34
std::shared_ptr< BgmResource > BgmResourcePtr
Definition: sound.h:78
const sound::XAudio2::SeResourcePtr getSoundEffect(size_t setId, const char *resId) const
Get sound effect resource pointer.
Definition: framework.cpp:611
double nextDouble(double a, double b)
Get next double random number.
Definition: framework.cpp:40
void createFixedString(std::array< char, N > *out, const char *src)
Create yappy::util::IdString from C-style string.
Definition: util.h:40
virtual void render()=0
Process rendering.
Debug utilities.
ResourceManager(size_t resSetCount=1)
Definition: framework.cpp:135
const sound::XAudio2::BgmResourcePtr getBgm(size_t setId, const char *resId) const
Definition: framework.cpp:277
void addBgmResource(size_t setId, const char *resId, const wchar_t *path)
Register BGM resource.
Definition: framework.cpp:576
void setSeed(unsigned int seed)
Set random seed.
Definition: framework.cpp:24
Game application main framework classes.
void writef(const wchar_t *fmt,...) noexcept
Write debug message using format string like printf.
Definition: debug.cpp:103
bool showCursor
Whether shows cursor or not.
Definition: framework.h:294
Application parameters.
Definition: framework.h:278
void loadResourceSet(size_t setId, std::atomic_bool &cancel)
Definition: framework.cpp:225
void addBgm(size_t setId, const char *resId, std::function< sound::XAudio2::BgmResourcePtr()> loadFunc)
Definition: framework.cpp:186
DirectGraphics manager.
Definition: graphics.h:80
const sound::XAudio2::BgmResourcePtr getBgm(size_t setId, const char *resId) const
Get BGM resource pointer.
Definition: framework.cpp:617
unsigned int nextRawUInt32()
Get next uint32 random number.
Definition: framework.cpp:29
virtual void init()=0
User initialization code.
void addSeResource(size_t setId, const char *resId, const wchar_t *path)
Register sound effect resource.
Definition: framework.cpp:567
const graphics::DGraphics::FontResourcePtr getFont(size_t setId, const char *resId) const
Definition: framework.cpp:265
#define ASSERT(x)
Assertion which uses debug framework.
Definition: debug.h:18
void addFont(size_t setId, const char *resId, std::function< graphics::DGraphics::FontResourcePtr()> loadFunc)
Definition: framework.cpp:174
void sealResource(bool seal)
Set the lock state of resources.
Definition: framework.cpp:585
Definition: config.cpp:6
uint32_t frameSkip
Frame skip count.
Definition: framework.h:292
void writeLine(const wchar_t *str=L"") noexcept
Write debug string and new line.
Definition: debug.h:64
std::shared_ptr< FontResource > FontResourcePtr
Definition: graphics.h:85
std::shared_ptr< SeResource > SeResourcePtr
Definition: sound.h:76
virtual void update()=0
Process frame.
void unloadResourceSet(size_t setId)
Definition: framework.cpp:233
int nCmdShow
nCmdShow from WinMain.
Definition: framework.h:282
char msg[LINE_DATA_SIZE-sizeof(LARGE_INTEGER)-sizeof(uint32_t)]
Definition: debug.cpp:159
void addTexture(size_t setId, const char *resId, std::function< graphics::DGraphics::TextureResourcePtr()> loadFunc)
Definition: framework.cpp:168
FrameControl(uint32_t fps, uint32_t skipCount)
Definition: framework.cpp:302
unsigned int generateRandomSeed()
Generate nondeterministic random number for seed.
Definition: framework.cpp:19
const graphics::DGraphics::FontResourcePtr getFont(size_t setId, const char *resId) const
Get font resource pointer.
Definition: framework.cpp:605
DirectInput8 wrapper.
Definition: input.h:16
std::shared_ptr< T > PtrType
Definition: framework.h:162
std::shared_ptr< TextureResource > TextureResourcePtr
Definition: graphics.h:83
void unloadResourceSet(size_t setId)
Unload resources by resource set ID.
Definition: framework.cpp:594
std::vector< std::wstring > parseCommandLine()
Command line utility.
Definition: framework.cpp:109
void checkWin32Result(bool cond, const std::string &msg)
Definition: exceptions.h:50
util::IdString IdString
Resource ID is fixed-length string; char[16].
Definition: framework.h:157
void addSoundEffect(size_t setId, const char *resId, std::function< sound::XAudio2::SeResourcePtr()> loadFunc)
Definition: framework.cpp:180
const graphics::DGraphics::TextureResourcePtr getTexture(size_t setId, const char *resId) const
Get texture resource pointer.
Definition: framework.cpp:599
const wchar_t * title
Window title string.
Definition: framework.h:286
void loadResourceSet(size_t setId, std::atomic_bool &cancel)
Load resources by resource set ID.
Definition: framework.cpp:590
Application(const AppParam &appParam, const graphics::GraphicsParam &graphParam, size_t resSetCount)
Constructor.
Definition: framework.cpp:377
const wchar_t * wndClsName
Window class name.
Definition: framework.h:284
double getFramePerSec() const
Definition: framework.cpp:365
virtual ~Application()
Destructor.
Definition: framework.cpp:446
User application base, which manages a window and DirectX objects.
Definition: framework.h:300
HICON hIconSm
hIconSm for window class.
Definition: framework.h:290
const graphics::DGraphics::TextureResourcePtr getTexture(size_t setId, const char *resId) const
Definition: framework.cpp:259