Index TOC Format: Export Simple Inline

Итак касаемо отрисовки предметов. Я наконец-то победил эту суку. Не знаю, насколько мой способ оптимальный и вообще стабильный. Но другого я пока не знаю

Что нужно чтобы отрисовать Texture2D на экране в SCP:SL

Шаг 1 Ищем s_GUIManager. Текущий его оффсет 0x1f03188 Найти его изи через PDBшку от нужной версии юнити

Шаг 2 Основа для этого шага взята из функции GUIManager::DoGUIEvent

  if (*(GUIManager **)(this + 8) == this) {
    this[0x10] = (GUIManager)0x0;
    goto LAB_180db5dc7;
  }

Как видно тут идёт проверка по оффсету 0x8 от GUIManager. Что же у нас там? Если поискать использования GUIManager, то можно найти IMGUIModule::AddGUIScript Там можно увидеть, что при передаче списка (List) экземпляров MonoBehaviour, они “сцепливаются” как раз с инстансом GUIManager

Мне было лень именно полноценно список реализовывать, поэтому я в лоб скопировал декомпилированную хуйню

    lVar1 = *(longlong *)guiManager;
    *(longlong *)param_1 = lVar1;
    *(GUIManager **)(param_1 + 8) = guiManager;
    *(ListNode<> **)(lVar1 + 8) = param_1;
    **(ListNode<> ***)(param_1 + 8) = param_1;

Таким образом, если мы “прицепим” к GUIManager любой MonoBehaviour, то методы, связанные с движковой отрисовкой будут вызываться

Шаг 3 Идём опять в GUIManager::DoGUIEvent и смотрим туда У нас тут разные методы типа

IMGUI::BeginWindows()
GUIObjectWrapper::DoGUI()
IMGUI::EndWindows()

и т.д.

Нас интересует GUIClipState::BeginOnGUI. Мы его хукаем. Почему именно он? Дело в том что в него вторым параметром передаётся InputEvent, который мы должны проверить на то, что он RepaintEvent. Иначе получим артефакты (не из сталкера) при отрисовке. Проверка делается так

void HookedBeginOnGUI(void *self, void *inputEvent) {
  originalInputEvent(self, inputEvent);

  // 7 - Repaint Event
  // 8 - Какой-то другой
  if(!inputEvent || ((uint8_t) ((uint8_t*) inputEvent)[0]) != 7) return;

  // TODO : Ваша отрисовка
}

Шаг 4 Реализуем отрисовку. Я для этого брал DrawClippedTexture, потому что там малое количество очевидных параметров

struct Rect {
      float x;
      float y;
      float width;
      float height;
    };

using DrawClippedTexture_t = void(
        __cdecl*)(Rect*, InternalTexture*, float, float, float, float, float*);

Стуктура Rect очевидна. Текстура - это текстура. Дальше идут 4 float’а, которые нам не интересны Вероятно это leftBorder,rightBorder и т.д. И последняя - это цвет в формате [0.0:1.0]

Вот и всё. Вызывать его, понятное дело, нужно в хуке BeginOnGui