<commit_before>#include "stdafx.h"

struct Screen
{
    int32_t Width;
    int32_t Height;
    int32_t Width43;
} Screen;

DWORD WINAPI WindowCheck(LPVOID hWnd)
{
    while (true)
    {
        Sleep(10);

        if (*(HWND*)hWnd && !IsWindow(*(HWND*)hWnd))
            ExitProcess(0);
    }
    return 0;
}

void Init()
{
    CIniReader iniReader("");
    Screen.Width = iniReader.ReadInteger("MAIN", "ResX", 0);
    Screen.Height = iniReader.ReadInteger("MAIN", "ResY", 0);
    bool bEndProcess = iniReader.ReadInteger("MAIN", "EndProcessOnWindowClose", 0) != 0;

    if (!Screen.Width || !Screen.Height)
        std::tie(Screen.Width, Screen.Height) = GetDesktopRes();

    Screen.Width43 = static_cast<uint32_t>(Screen.Height * (4.0f / 3.0f));

    //wndmode crashfix
    auto pattern = hook::pattern("E8 ? ? ? ? 83 C4 04 B8 01 00 00 00 5D 5F 5E 5B 81 C4 70 05 00 00"); //0x49225B
    injector::MakeNOP(pattern.get_first(0), 5, true);

    //Player_a bugfix
    pattern = hook::pattern("88 1D ? ? ? ? 88 1D ? ? ? ? C6 05 ? ? ? ? 01 88 1D ? ? ? ? C7 05"); //0x42B512
    static auto byte_51029C = *pattern.get_first<uint8_t*>(2);
    struct patch_player_a
    {
        void operator()(injector::reg_pack& regs)
        {
            *byte_51029C = 0x06;
        }
    };
    injector::MakeInline<patch_player_a>(pattern.get_first(0), pattern.get_first(6));
    pattern = hook::pattern("A2 ? ? ? ? E8 ? ? ? ? 8B F0 83"); //0x4274FF
    injector::MakeInline<patch_player_a>(pattern.get_first(0));

    //Res change
    pattern = hook::pattern("A3 ? ? ? ? A3 ? ? ? ? 8B 83 B4 01 00 00 40"); //0x491E4C
    static auto nWidth = *pattern.get_first<uint32_t*>(1);
    static auto dword_787370 = *pattern.get_first<uint32_t*>(6);
    static auto nHeight = *pattern.get_first<uint32_t*>(20);
    static auto dword_787388 = *pattern.get_first<uint32_t*>(25);
    struct SetResHook
    {
        void operator()(injector::reg_pack& regs)
        {
            *nWidth = Screen.Width;
            *dword_787370 = Screen.Width;
            regs.eax = Screen.Height;
        }
    }; injector::MakeInline<SetResHook>(pattern.get_first(0), pattern.get_first(17));

    pattern = hook::pattern("89 B1 ? ? ? ? D1 F8 89 81"); //0x46453B
    static auto dword_74F168 = *pattern.get_first<uint32_t>(2);
    struct SetResHook43
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.esi = Screen.Width43;
            *(uint32_t*)(regs.ecx + dword_74F168) = regs.esi;
        }
    }; injector::MakeInline<SetResHook43>(pattern.get_first(0), pattern.get_first(6));

    pattern = hook::pattern("8B 4C 24 04 8B 81 40 02 00 00"); //0x48C1A0
    struct SetResHookX
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = Screen.Width - 1;
        }
    }; injector::MakeInline<SetResHookX>(pattern.get_first(0), pattern.get_first(19));

    pattern = hook::pattern("A3 ? ? ? ? E8 ? ? ? ? 83 C4 08 40 83"); //0x414FF7
    static auto dword_504CC0 = *pattern.get_first<uint32_t*>(1);
    struct SetResHookX1
    {
        void operator()(injector::reg_pack& regs)
        {
            *dword_504CC0 = Screen.Width;
        }
    }; injector::MakeInline<SetResHookX1>(pattern.get_first(0));

    pattern = hook::pattern("89 15 ? ? ? ? 8B 40 0C A3 ? ? ? ? C3"); //0x43B7CF
    static auto dword_5C0C00 = *pattern.get_first<uint32_t*>(2);
    struct SetResHookX2
    {
        void operator()(injector::reg_pack& regs)
        {
            *dword_5C0C00 = Screen.Width;
        }
    }; injector::MakeInline<SetResHookX2>(pattern.get_first(0), pattern.get_first(6));

    pattern = hook::pattern("8B 4C 24 04 8B 81 44 02 00 00 8B 91"); //0x48C1C0
    struct SetResHookY
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = Screen.Height - 1;
        }
    }; injector::MakeInline<SetResHookY>(pattern.get_first(0), pattern.get_first(19));

    //Menu fix
    pattern = hook::pattern("BB ? ? ? ? 2B 5D 0C D1 E3 89 5D FC"); //0x4898C3
    injector::WriteMemory(pattern.get_first(1), Screen.Width, true);

    //FMV crashfix
    static int n480 = 480;
    pattern = hook::pattern("A1 ? ? ? ? 74 56 85 C0 0F");
    injector::WriteMemory(pattern.get_first(1), &n480, true); //42D83A
    pattern = hook::pattern("3B 15 ? ? ? ? 7C B7 5B 5F 5E C3");
    injector::WriteMemory(pattern.get_first(2), &n480, true); //42D88B
    pattern = hook::pattern("3B 15 ? ? ? ? 7C C7 5F 5E C3");
    injector::WriteMemory(pattern.get_first(2), &n480, true); //42D8CC

    if (bEndProcess)
    {
        pattern = hook::pattern("3B 05 ? ? ? ? 0F 94 C3 85 DB"); //0x4B4FB8
        auto hwnd = *pattern.get_first<HWND*>(2);
        CreateThreadAutoClose(0, 0, (LPTHREAD_START_ROUTINE)&WindowCheck, (LPVOID)hwnd, 0, NULL);
    }
}

CEXP void InitializeASI()
{
    std::call_once(CallbackHandler::flag, []()
        {
            CallbackHandler::RegisterCallback(Init, hook::pattern("83 EC 0C 33 C0 53 57 33 DB"));
        });
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved)
{
    if (reason == DLL_PROCESS_ATTACH)
    {
        if (!IsUALPresent()) { InitializeASI(); }
    }
    return TRUE;
}<commit_msg>gta1 update<commit_after>#include "stdafx.h"

struct Screen
{
    int32_t Width;
    int32_t Height;
    int32_t Width43;
} Screen;

DWORD WINAPI WindowCheck(LPVOID hWnd)
{
    while (true)
    {
        Sleep(10);

        if (*(HWND*)hWnd && !IsWindow(*(HWND*)hWnd))
            ExitProcess(0);
    }
    return 0;
}

void InitGtaClassicsSteam()
{
    // Patches:
    // - GTA1 Rockstar Classics & Steam: SHA256=6A5C313D9C0D87B4EFA527BAAC7097DD4A149B9B2DA5261ABB224083F5CDC1C2 (774144 bytes)

    CIniReader iniReader("");
    Screen.Width = iniReader.ReadInteger("MAIN", "ResX", 0);
    Screen.Height = iniReader.ReadInteger("MAIN", "ResY", 0);
    bool bEndProcess = iniReader.ReadInteger("MAIN", "EndProcessOnWindowClose", 0) != 0;

    if (!Screen.Width || !Screen.Height)
        std::tie(Screen.Width, Screen.Height) = GetDesktopRes();

    Screen.Width43 = static_cast<uint32_t>(Screen.Height * (4.0f / 3.0f));

    //wndmode crashfix (caused by the ASI loader)
    auto pattern = hook::pattern("E8 ? ? ? ? 83 C4 04 B8 01 00 00 00 5D 5F 5E 5B 81 C4 70 05 00 00"); //0x49225B
    injector::MakeNOP(pattern.get_first(0), 5, true);

    //Player_a bugfix (only in the Rockstar Classics / Steam version)
    //Fix by Daniel Marschall,
    //see technical details here: https://misc.daniel-marschall.de/spiele/gta1/player_a_bugfix.txt
    pattern = hook::pattern("3B C2 0F 9D C2 FE CA 83 E2 06");
    if (!pattern.empty()) { // This patch is optional; if pattern does not exist, then do nothing.
        struct patch_player_a_new
        {
            void operator()(injector::reg_pack& regs)
            {
                // mov     al, [ecx] ; ecx is a pointer to the saved resolution (values 0..5)
                // cmp     eax, edx  ; <-- Patch: mov edx, eax
                // setnl   dl        ; <-- Patch: nop
                // dec     dl        ; <-- Patch: nop
                // and     edx, 6    ; <-- Patch: nop (Bug is in this line: Resolution "6" does not exist!)
                // mov     byte ptr byte_00503224, dl  ; In byte_00503224, the to-be-applied resolution will be saved
                regs.edx = regs.eax;
            }
        };
        injector::MakeInline<patch_player_a_new>(pattern.get_first(0), pattern.get_first(10));
    }

    //Res change
    pattern = hook::pattern("A3 ? ? ? ? A3 ? ? ? ? 8B 83 B4 01 00 00 40"); //0x491E4C
    static auto nWidth = *pattern.get_first<uint32_t*>(1);
    static auto dword_787370 = *pattern.get_first<uint32_t*>(6);
    //static auto nHeight = *pattern.get_first<uint32_t*>(20);
    //static auto dword_787388 = *pattern.get_first<uint32_t*>(25);
    struct SetResHook
    {
        void operator()(injector::reg_pack& regs)
        {
            *nWidth = Screen.Width;
            *dword_787370 = Screen.Width;
            regs.eax = Screen.Height;
        }
    }; injector::MakeInline<SetResHook>(pattern.get_first(0), pattern.get_first(17));

    pattern = hook::pattern("89 B1 ? ? ? ? D1 F8 89 81"); //0x46453B
    static auto dword_74F168 = *pattern.get_first<uint32_t>(2);
    struct SetResHook43
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.esi = Screen.Width43;
            *(uint32_t*)(regs.ecx + dword_74F168) = regs.esi;
        }
    }; injector::MakeInline<SetResHook43>(pattern.get_first(0), pattern.get_first(6));

    pattern = hook::pattern("8B 4C 24 04 8B 81 40 02 00 00"); //0x48C1A0
    struct SetResHookX
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = Screen.Width - 1;
        }
    }; injector::MakeInline<SetResHookX>(pattern.get_first(0), pattern.get_first(19));

    pattern = hook::pattern("A3 ? ? ? ? E8 ? ? ? ? 83 C4 08 40 83"); //0x414FF7
    static auto dword_504CC0 = *pattern.get_first<uint32_t*>(1);
    struct SetResHookX1
    {
        void operator()(injector::reg_pack& regs)
        {
            *dword_504CC0 = Screen.Width;
        }
    }; injector::MakeInline<SetResHookX1>(pattern.get_first(0));

    pattern = hook::pattern("89 15 ? ? ? ? 8B 40 0C A3 ? ? ? ? C3"); //0x43B7CF
    static auto dword_5C0C00 = *pattern.get_first<uint32_t*>(2);
    struct SetResHookX2
    {
        void operator()(injector::reg_pack& regs)
        {
            *dword_5C0C00 = Screen.Width;
        }
    }; injector::MakeInline<SetResHookX2>(pattern.get_first(0), pattern.get_first(6));

    pattern = hook::pattern("8B 4C 24 04 8B 81 44 02 00 00 8B 91"); //0x48C1C0
    struct SetResHookY
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = Screen.Height - 1;
        }
    }; injector::MakeInline<SetResHookY>(pattern.get_first(0), pattern.get_first(19));

    //Menu fix
    pattern = hook::pattern("BB ? ? ? ? 2B 5D 0C D1 E3 89 5D FC"); //0x4898C3
    injector::WriteMemory(pattern.get_first(1), Screen.Width, true);

    //Fix crash in FMV (cut scenes) due to the resolution change
    static int n480 = 480; // fix dword_785174
    pattern = hook::pattern("A1 ? ? ? ? 74 56 85 C0 0F");
    injector::WriteMemory(pattern.get_first(1), &n480, true); //42D83A
    pattern = hook::pattern("3B 15 ? ? ? ? 7C B7 5B 5F 5E C3");
    injector::WriteMemory(pattern.get_first(2), &n480, true); //42D88B
    pattern = hook::pattern("3B 15 ? ? ? ? 7C C7 5F 5E C3");
    injector::WriteMemory(pattern.get_first(2), &n480, true); //42D8CC

    if (bEndProcess)
    {
        pattern = hook::pattern("3B 05 ? ? ? ? 0F 94 C3 85 DB"); //0x4B4FB8
        auto hwnd = *pattern.get_first<HWND*>(2);
        CreateThreadAutoClose(0, 0, (LPTHREAD_START_ROUTINE)&WindowCheck, (LPVOID)hwnd, 0, NULL);
    }
}

// TODO: GTA 1 Retail, London 1969 and London 1961:
//       The game crashes if a cut scene is replayed (space bar), most likely because of a timer issue:
//       They are heavily accelerated (like the menu).
//       The cut scenes do work when they are triggered via mission complete.

void InitLondonRetail()
{
    // Patches:
    // - GTA London 1969 Retail (CD): SHA256=1FA3934F330B0097A0CB8160E3968D78E93CB4A808703AD4854BDB1F87BAE39A (1231360 bytes)
    // - GTA London 1961 (Download):  SHA256=549020E49AAD17D1EF26BC5766A8374503C5A5936251B793BF8BE2A1D90700C5 (1235968 bytes)

    // Note: Variable names in this function (dword_...) are taken from GTA London 1969, not 1961

    CIniReader iniReader("");
    Screen.Width = iniReader.ReadInteger("MAIN", "ResX", 0);
    Screen.Height = iniReader.ReadInteger("MAIN", "ResY", 0);
    bool bEndProcess = iniReader.ReadInteger("MAIN", "EndProcessOnWindowClose", 0) != 0;

    if (!Screen.Width || !Screen.Height)
        std::tie(Screen.Width, Screen.Height) = GetDesktopRes();

    Screen.Width43 = static_cast<uint32_t>(Screen.Height * (4.0f / 3.0f));

    //wndmode crashfix (caused by the ASI loader)
    auto pattern = hook::pattern("E8 ? ? ? ? 83 C4 04 B8 01 00 00 00 5D 5F 5E 5B 81 C4 70 05 00 00");
    injector::MakeNOP(pattern.get_first(0), 5, true);

    //Res change
    pattern = hook::pattern("A3 ? ? ? ? A3 ? ? ? ? 8B 83 B4 01 00 00 40");
    static auto nWidth = *pattern.get_first<uint32_t*>(1);
    static auto dword_854C30 = *pattern.get_first<uint32_t*>(6);
    //static auto nHeight = *pattern.get_first<uint32_t*>(20);
    //static auto dword_854C48 = *pattern.get_first<uint32_t*>(25);
    struct SetResHook
    {
        void operator()(injector::reg_pack& regs)
        {
            *nWidth = Screen.Width;
            *dword_854C30 = Screen.Width;
            regs.eax = Screen.Height;
        }
    }; injector::MakeInline<SetResHook>(pattern.get_first(0), pattern.get_first(17));

    pattern = hook::pattern("8B 81 ? ? ? ? 99 2B C2 D1 F8");
    static auto dword_80CF48 = *pattern.get_first<uint32_t>(2);
    struct SetResHook43
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = *(uint32_t*)(regs.ecx + dword_80CF48);
            regs.esi = Screen.Width43;
            *(uint32_t*)(regs.ecx + dword_80CF48) = regs.esi;
        }
    }; injector::MakeInline<SetResHook43>(pattern.get_first(0), pattern.get_first(6));

    pattern = hook::pattern("8B 4C 24 04 8B 81 40 02 00 00 8B 91 38 02 00 00 2B");
    struct SetResHookX
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = Screen.Width - 1;
        }
    }; injector::MakeInline<SetResHookX>(pattern.get_first(0), pattern.get_first(19));

    pattern = hook::pattern("A1 ? ? ? ? 83 C4 08 40 83");
    static auto dword_55128C = *pattern.get_first<uint32_t*>(1);
    struct SetResHookX1
    {
        void operator()(injector::reg_pack& regs)
        {
            *dword_55128C = Screen.Width;
        }
    }; injector::MakeInline<SetResHookX1>(pattern.get_first(0));

    pattern = hook::pattern("89 15 ? ? ? ? 8B 40 0C A3 ? ? ? ? C3");
    static auto dword_626638 = *pattern.get_first<uint32_t*>(2);
    struct SetResHookX2
    {
        void operator()(injector::reg_pack& regs)
        {
            *dword_626638 = Screen.Width;
        }
    }; injector::MakeInline<SetResHookX2>(pattern.get_first(0), pattern.get_first(6));

    pattern = hook::pattern("8B 4C 24 04 8B 81 44 02 00 00 8B 91");
    struct SetResHookY
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = Screen.Height - 1;
        }
    }; injector::MakeInline<SetResHookY>(pattern.get_first(0), pattern.get_first(19));

    //Menu fix
    pattern = hook::pattern("BB ? ? ? ? 2B 5D 0C D1 E3 89 5D FC");
    injector::WriteMemory(pattern.get_first(1), Screen.Width, true);

    //Fix crash in FMV (cut scenes) due to the resolution change
    static int n480 = 480;
    pattern = hook::pattern("A1 ? ? ? ? 33 D2 85 C0 0F ? ? ? ?");
    injector::WriteMemory(pattern.get_first(1), &n480, true);
    pattern = hook::pattern("42 F3 A4 3B 15 ? ? ? ? 7C B7 5F 5E");
    injector::WriteMemory(pattern.get_first(5), &n480, true);
    pattern = hook::pattern("A1 ? ? ? ? 33 D2 85 C0 7E 39 8B FA");
    injector::WriteMemory(pattern.get_first(1), &n480, true);
    pattern = hook::pattern("42 F3 AA 3B 15 ? ? ? ? 7C C7 5F 5E");
    injector::WriteMemory(pattern.get_first(5), &n480, true);

    if (bEndProcess)
    {
        pattern = hook::pattern("3B 05 ? ? ? ? 0F 94 C3 85 DB");
        auto hwnd = *pattern.get_first<HWND*>(2);
        CreateThreadAutoClose(0, 0, (LPTHREAD_START_ROUTINE)&WindowCheck, (LPVOID)hwnd, 0, NULL);
    }
}

void InitGtaRetail()
{
    // Patches:
    // - GTA1 Retail (CD): SHA256=5AF3C1D90A85F694B184F3FC242E5F8F13B01BFE9BC706C655E97B7BC21599C8 (909824 bytes)

    CIniReader iniReader("");
    Screen.Width = iniReader.ReadInteger("MAIN", "ResX", 0);
    Screen.Height = iniReader.ReadInteger("MAIN", "ResY", 0);
    bool bEndProcess = iniReader.ReadInteger("MAIN", "EndProcessOnWindowClose", 0) != 0;

    if (!Screen.Width || !Screen.Height)
        std::tie(Screen.Width, Screen.Height) = GetDesktopRes();

    Screen.Width43 = static_cast<uint32_t>(Screen.Height * (4.0f / 3.0f));

    //wndmode crashfix (caused by the ASI loader)
    auto pattern = hook::pattern("E8 ? ? ? ? 83 C4 04 B8 01 00 00 00 5D 5F 5E 5B 81 C4 70 05 00 00");
    injector::MakeNOP(pattern.get_first(0), 5, true);

    //Res change
    pattern = hook::pattern("A3 ? ? ? ? A3 ? ? ? ? 8B 83 B4 01 00 00 40");
    static auto nWidth = *pattern.get_first<uint32_t*>(1);
    static auto dword_77E990 = *pattern.get_first<uint32_t*>(6);
    //static auto nHeight = *pattern.get_first<uint32_t*>(20);
    //static auto dword_77E9A8 = *pattern.get_first<uint32_t*>(25);
    struct SetResHook
    {
        void operator()(injector::reg_pack& regs)
        {
            *nWidth = Screen.Width;
            *dword_77E990 = Screen.Width;
            regs.eax = Screen.Height;
        }
    }; injector::MakeInline<SetResHook>(pattern.get_first(0), pattern.get_first(17));

    pattern = hook::pattern("8B 86 ? ? ? ? 99 2B C2 D1 F8 8D 0C 49");
    static auto dword_6575E8 = *pattern.get_first<uint32_t>(2);
    struct SetResHook43
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = *(uint32_t*)(regs.esi + dword_6575E8);
            regs.ecx = Screen.Width43;
            *(uint32_t*)(regs.esi + dword_6575E8) = regs.ecx;
        }
    }; injector::MakeInline<SetResHook43>(pattern.get_first(0), pattern.get_first(6));

    pattern = hook::pattern("8B 4C 24 04 8B 81 40 02 00 00 8B 91 38 02 00 00 2B");
    struct SetResHookX
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = Screen.Width - 1;
        }
    }; injector::MakeInline<SetResHookX>(pattern.get_first(0), pattern.get_first(19));

    pattern = hook::pattern("A1 ? ? ? ? 40 A3 10");
    static auto dword_4BF010 = *pattern.get_first<uint32_t*>(1);
    struct SetResHookX1
    {
        void operator()(injector::reg_pack& regs)
        {
            *dword_4BF010 = Screen.Width;
        }
    }; injector::MakeInline<SetResHookX1>(pattern.get_first(0));

    pattern = hook::pattern("89 15 ? ? ? ? 8B 40 0C A3 ? ? ? ? C3");
    static auto dword_5F18E8 = *pattern.get_first<uint32_t*>(2);
    struct SetResHookX2
    {
        void operator()(injector::reg_pack& regs)
        {
            *dword_5F18E8 = Screen.Width;
        }
    }; injector::MakeInline<SetResHookX2>(pattern.get_first(0), pattern.get_first(6));

    pattern = hook::pattern("8B 4C 24 04 8B 81 44 02 00 00 8B 91");
    struct SetResHookY
    {
        void operator()(injector::reg_pack& regs)
        {
            regs.eax = Screen.Height - 1;
        }
    }; injector::MakeInline<SetResHookY>(pattern.get_first(0), pattern.get_first(19));

    //Menu fix
    pattern = hook::pattern("BB ? ? ? ? 2B 5D 0C D1 E3 89 5D FC");
    injector::WriteMemory(pattern.get_first(1), Screen.Width, true);

    //Fix crash in FMV (cut scenes) due to the resolution change
    static int n480 = 480;
    pattern = hook::pattern("A1 ? ? ? ? 89 54 24 10 3B C2 0F 8E 95 00 00 00");
    injector::WriteMemory(pattern.get_first(1), &n480, true);
    pattern = hook::pattern("42 03 F3 F3 A5 3B 15 ? ? ? ? 7C B1");
    injector::WriteMemory(pattern.get_first(7), &n480, true);
    pattern = hook::pattern("33 D2 A1 ? ? ? ? 3B C2 7E 33");
    injector::WriteMemory(pattern.get_first(3), &n480, true);
    pattern = hook::pattern("F3 AB 3B 15 ? ? ? ? 7C CD");
    injector::WriteMemory(pattern.get_first(4), &n480, true);

    if (bEndProcess)
    {
        pattern = hook::pattern("3B 05 ? ? ? ? 0F 94 C3 85 DB");
        auto hwnd = *pattern.get_first<HWND*>(2);
        CreateThreadAutoClose(0, 0, (LPTHREAD_START_ROUTINE)&WindowCheck, (LPVOID)hwnd, 0, NULL);
    }
}

CEXP void InitializeASI()
{
    std::call_once(CallbackHandler::flag, []()
        {
            CallbackHandler::RegisterCallback(InitGtaClassicsSteam, hook::pattern("83 EC 0C 33 C0 53 57 33 DB"));

            CallbackHandler::RegisterCallback(InitLondonRetail, hook::pattern("51 53 55 56 68 ? ? ? ? 33 DB"));

            CallbackHandler::RegisterCallback(InitGtaRetail, hook::pattern("53 56 57 55 33 ED 68 ? ? ? ? E8"));
        });
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved)
{
    if (reason == DLL_PROCESS_ATTACH)
    {
        if (!IsUALPresent()) { InitializeASI(); }
    }
    return TRUE;
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: surfaceModel.C,v 1.19 2002/12/17 18:39:18 amoll Exp $

#include <BALL/MOLVIEW/FUNCTOR/surfaceModel.h>
#include <BALL/KERNEL/system.h>
#include <BALL/STRUCTURE/surfaceProcessor.h>
#include <BALL/MOLVIEW/FUNCTOR/molecularInformation.h>
#include <BALL/KERNEL/system.h>

using namespace std;

namespace BALL
{
	namespace MOLVIEW
	{

		AddSurfaceModel::AddSurfaceModel()
			throw()
			: BaseModelProcessor(),
				get_composite_(true),
				start_composite_(0)
		{
		}

		AddSurfaceModel::AddSurfaceModel(const AddSurfaceModel& add_surface, bool deep)
			throw()
			:	BaseModelProcessor(add_surface, deep),
				get_composite_(true),
				start_composite_(0)
		{
		}

		AddSurfaceModel::~AddSurfaceModel()
			throw()
		{
			#ifdef BALL_VIEW_DEBUG
				Log.error() << "Destructing object " << (void *)this
										<< " of class " << RTTI::getName<AddSurfaceModel>() << endl;
			#endif

			destroy();
		}

		void AddSurfaceModel::clear()
			throw()
		{
			BaseModelProcessor::clear();
			get_composite_ = true;
			start_composite_ = 0;
		}

		void AddSurfaceModel::destroy()
			throw()
		{
		}

		bool AddSurfaceModel::start()
		{
			get_composite_ = true;
			start_composite_ = 0;
			return BaseModelProcessor::start();
		}

		bool AddSurfaceModel::finish()
		{
			// insert surface only if a composite exist
			if (start_composite_ == 0 ||
					RTTI::isKindOf<GeometricObject>(*start_composite_))
			{
				return false;
			}

			Mesh* mesh = createMesh_();

			if (mesh == 0)
			{
				throw Exception::OutOfMemory(__FILE__, __LINE__, sizeof(Mesh));
			}

			// get info from the start composite
			MolecularInformation molecular_information;
			start_composite_->host(molecular_information);

			mesh->PropertyManager::set(*this);

			SurfaceProcessor sp;
			try
			{
				start_composite_->apply(sp);
			}
			catch (Exception::GeneralException e)
			{
				Log.error() << "SurfaceModel: caught exception while calculating molecular surface: " << e << endl;
			}
			catch (std::exception e)
			{
				Log.error() << "SurfaceModel: caught exception while calculating molecular surface: " << e.what() << endl;
			}
			catch (...)
			{
				Log.error() << "SurfaceModel: caught unknown exception while calculating molecular surface" << endl;
			}
			Log.info() << "assigning surface (" << sp.getSurface().vertex.size() << " vertices, "
								 << sp.getSurface().triangle.size() << " triangles)" << endl;

			*static_cast<Surface*>(mesh) = sp.getSurface();

			mesh->setName(String("Surface of ")
										+ molecular_information.getTypeName()
										+ String(" (")
										+ molecular_information.getName()
										+ String(")"));

			start_composite_->getRoot().appendChild(*mesh);
			return true;
		}

		Processor::Result AddSurfaceModel::operator () (Composite& composite)
		{
			// take first composite, surface will be inserted to it later
			if (get_composite_)
			{
				start_composite_ = &composite;
				get_composite_ = false;
			}

			return Processor::CONTINUE;
		}

		void AddSurfaceModel::dump(std::ostream& s, Size depth) const
			throw()
		{
			BALL_DUMP_STREAM_PREFIX(s);

			BALL_DUMP_DEPTH(s, depth);
			BALL_DUMP_HEADER(s, this, this);

			BaseModelProcessor::dump(s, depth + 1);

			BALL_DUMP_STREAM_SUFFIX(s);
		}

		Mesh*	AddSurfaceModel::createMesh_()
		{
			return (Mesh *)(new Mesh());
		}

	} // namespace MOLVIEW

} // namespace BALL
<commit_msg>added support for different detailled surfaces<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: surfaceModel.C,v 1.20 2002/12/18 03:14:02 amoll Exp $

#include <BALL/MOLVIEW/FUNCTOR/surfaceModel.h>
#include <BALL/STRUCTURE/surfaceProcessor.h>
#include <BALL/MOLVIEW/FUNCTOR/molecularInformation.h>

using namespace std;

namespace BALL
{
	namespace MOLVIEW
	{

		AddSurfaceModel::AddSurfaceModel()
			throw()
			: BaseModelProcessor(),
				get_composite_(true),
				start_composite_(0)
		{
		}

		AddSurfaceModel::AddSurfaceModel(const AddSurfaceModel& add_surface, bool deep)
			throw()
			:	BaseModelProcessor(add_surface, deep),
				get_composite_(true),
				start_composite_(0)
		{
		}

		AddSurfaceModel::~AddSurfaceModel()
			throw()
		{
			#ifdef BALL_VIEW_DEBUG
				Log.error() << "Destructing object " << (void *)this
										<< " of class " << RTTI::getName<AddSurfaceModel>() << endl;
			#endif

			destroy();
		}

		void AddSurfaceModel::clear()
			throw()
		{
			BaseModelProcessor::clear();
			get_composite_ = true;
			start_composite_ = 0;
		}

		void AddSurfaceModel::destroy()
			throw()
		{
		}

		bool AddSurfaceModel::start()
		{
			get_composite_ = true;
			start_composite_ = 0;
			return BaseModelProcessor::start();
		}

		bool AddSurfaceModel::finish()
		{
			// insert surface only if a composite exist
			if (start_composite_ == 0 ||
					RTTI::isKindOf<GeometricObject>(*start_composite_))
			{
				return false;
			}

			Mesh* mesh = createMesh_();

			if (mesh == 0)
			{
				throw Exception::OutOfMemory(__FILE__, __LINE__, sizeof(Mesh));
			}

			// get info from the start composite
			MolecularInformation molecular_information;
			start_composite_->host(molecular_information);

			mesh->PropertyManager::set(*this);

			SurfaceProcessor sp;

			if (hasProperty(GeometricObject::PROPERTY__DRAWING_PRECISION_LOW))
			{
				sp.setDensity(2.0);
			}
			else if (hasProperty(GeometricObject::PROPERTY__DRAWING_PRECISION_MEDIUM))
			{
				sp.setDensity(4.5);
			}
			else if (hasProperty(GeometricObject::PROPERTY__DRAWING_PRECISION_HIGH))
			{
				sp.setDensity(7.0);
			}
			else
			{
				Log.error() << "Unknown precision in " << __FILE__ << "   " << __LINE__ << std::endl;
			}

			try
			{
				start_composite_->apply(sp);
			}
			catch (Exception::GeneralException e)
			{
				Log.error() << "SurfaceModel: caught exception while calculating molecular surface: " << e << endl;
			}
			catch (std::exception e)
			{
				Log.error() << "SurfaceModel: caught exception while calculating molecular surface: " << e.what() << endl;
			}
			catch (...)
			{
				Log.error() << "SurfaceModel: caught unknown exception while calculating molecular surface" << endl;
			}
			Log.info() << "assigning surface (" << sp.getSurface().vertex.size() << " vertices, "
								 << sp.getSurface().triangle.size() << " triangles)" << endl;

			*static_cast<Surface*>(mesh) = sp.getSurface();

			mesh->setName(String("Surface of ")
										+ molecular_information.getTypeName()
										+ String(" (")
										+ molecular_information.getName()
										+ String(")"));

			start_composite_->getRoot().appendChild(*mesh);
			return true;
		}

		Processor::Result AddSurfaceModel::operator () (Composite& composite)
		{
			// take first composite, surface will be inserted to it later
			if (get_composite_)
			{
				start_composite_ = &composite;
				get_composite_ = false;
			}

			return Processor::CONTINUE;
		}

		void AddSurfaceModel::dump(std::ostream& s, Size depth) const
			throw()
		{
			BALL_DUMP_STREAM_PREFIX(s);

			BALL_DUMP_DEPTH(s, depth);
			BALL_DUMP_HEADER(s, this, this);

			BaseModelProcessor::dump(s, depth + 1);

			BALL_DUMP_STREAM_SUFFIX(s);
		}

		Mesh*	AddSurfaceModel::createMesh_()
		{
			return (Mesh *)(new Mesh());
		}

	} // namespace MOLVIEW

} // namespace BALL
<|endoftext|>


<commit_before>#include <reflection/reflection.h>

REFLECTABLE(auto, operator!=,   member_function);
REFLECTABLE(auto, operator%,    member_function);
REFLECTABLE(auto, operator%=,   member_function);
REFLECTABLE(auto, operator&,    member_function);
REFLECTABLE(auto, operator&&,   member_function);
REFLECTABLE(auto, operator&=,   member_function);
REFLECTABLE(auto, operator(),   member_function);
REFLECTABLE(auto, operator*,    member_function);
REFLECTABLE(auto, operator*=,   member_function);
REFLECTABLE(auto, operator+,    member_function);
REFLECTABLE(auto, operator++,   member_function);
REFLECTABLE(auto, operator+=,   member_function);
REFLECTABLE(auto, operator-,    member_function);
REFLECTABLE(auto, operator--,   member_function);
REFLECTABLE(auto, operator-=,   member_function);
REFLECTABLE(auto, operator->*,  member_function);
REFLECTABLE(auto, operator/,    member_function);
REFLECTABLE(auto, operator/=,   member_function);
REFLECTABLE(auto, operator<,    member_function);
REFLECTABLE(auto, operator<<,   member_function);
REFLECTABLE(auto, operator<<=,  member_function);
REFLECTABLE(auto, operator<=,   member_function);
REFLECTABLE(auto, operator=,    member_function);
REFLECTABLE(auto, operator==,   member_function);
REFLECTABLE(auto, operator>,    member_function);
REFLECTABLE(auto, operator>=,   member_function);
REFLECTABLE(auto, operator>>,   member_function);
REFLECTABLE(auto, operator>>=,  member_function);
REFLECTABLE(auto, operator[],   member_function);
REFLECTABLE(auto, operator|,    member_function);
REFLECTABLE(auto, operator|=,   member_function);
REFLECTABLE(auto, operator||,   member_function);
REFLECTABLE(auto, operator^=,   member_function);

REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator!,   member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator->,  member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator~,   member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator^,   member_function);

// TODO: operator,
// #define REFLECTION_OPERATOR_COMMA operator,
// REFLECTABLE(auto, REFLECTION_OPERATOR_COMMA,  member_function);
<commit_msg>Removed superfluous newline<commit_after>#include <reflection/reflection.h>

REFLECTABLE(auto, operator!=,   member_function);
REFLECTABLE(auto, operator%,    member_function);
REFLECTABLE(auto, operator%=,   member_function);
REFLECTABLE(auto, operator&,    member_function);
REFLECTABLE(auto, operator&&,   member_function);
REFLECTABLE(auto, operator&=,   member_function);
REFLECTABLE(auto, operator(),   member_function);
REFLECTABLE(auto, operator*,    member_function);
REFLECTABLE(auto, operator*=,   member_function);
REFLECTABLE(auto, operator+,    member_function);
REFLECTABLE(auto, operator++,   member_function);
REFLECTABLE(auto, operator+=,   member_function);
REFLECTABLE(auto, operator-,    member_function);
REFLECTABLE(auto, operator--,   member_function);
REFLECTABLE(auto, operator-=,   member_function);
REFLECTABLE(auto, operator->*,  member_function);
REFLECTABLE(auto, operator/,    member_function);
REFLECTABLE(auto, operator/=,   member_function);
REFLECTABLE(auto, operator<,    member_function);
REFLECTABLE(auto, operator<<,   member_function);
REFLECTABLE(auto, operator<<=,  member_function);
REFLECTABLE(auto, operator<=,   member_function);
REFLECTABLE(auto, operator=,    member_function);
REFLECTABLE(auto, operator==,   member_function);
REFLECTABLE(auto, operator>,    member_function);
REFLECTABLE(auto, operator>=,   member_function);
REFLECTABLE(auto, operator>>,   member_function);
REFLECTABLE(auto, operator>>=,  member_function);
REFLECTABLE(auto, operator[],   member_function);
REFLECTABLE(auto, operator|,    member_function);
REFLECTABLE(auto, operator|=,   member_function);
REFLECTABLE(auto, operator||,   member_function);
REFLECTABLE(auto, operator^=,   member_function);

REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator!,   member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator->,  member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator~,   member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator^,   member_function);

// TODO: operator,
// #define REFLECTION_OPERATOR_COMMA operator,
// REFLECTABLE(auto, REFLECTION_OPERATOR_COMMA,  member_function);
<|endoftext|>


<commit_before>/*
Copyright (c) 2019 -> Present Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include"hip/hip_runtime.h"

extern "C" __global__ void matmulK(int* A, int* B, int* C, int N) {

    int ROW = blockIdx.y*blockDim.y+threadIdx.y;
    int COL = blockIdx.x*blockDim.x+threadIdx.x;
    int tmpSum = 0;

        if (ROW < N && COL < N) {
   // each thread computes one element of the block sub-matrix
         for (int i = 0; i < N; i++) {
             tmpSum += A[ROW * N + i] * B[i * N + COL];
                           }
         }
        C[ROW * N + COL] =tmpSum;
}

extern "C" __global__ void WaitKernel() {

	unsigned long long int wait_t=32000000000,start=clock64(),cur;
        do{cur=clock64()-start;}
        while(cur<wait_t);
}

<commit_msg>Formatting changes<commit_after>/*
Copyright (c) 2019 - present Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include"hip/hip_runtime.h"

extern "C" __global__ void matmulK(int* A, int* B, int* C, int N) {
    int ROW = blockIdx.y*blockDim.y+threadIdx.y;
    int COL = blockIdx.x*blockDim.x+threadIdx.x;
    int tmpSum = 0;
    if (ROW < N && COL < N) {
        // each thread computes one element of the block sub-matrix
        for (int i = 0; i < N; i++) {
            tmpSum += A[ROW * N + i] * B[i * N + COL];
        }
    }
    C[ROW * N + COL] =tmpSum;
}

extern "C" __global__ void WaitKernel() {
	unsigned long long int wait_t=32000000000,start=clock64(),cur;
    do{cur=clock64()-start;}
    while(cur<wait_t);
}
<|endoftext|>


<commit_before>/* Jim Viebke
Jun 3 2015 */

#include "npc_enemy.h"

void Hostile_NPC::update(World & world, map<string, shared_ptr<Character>> & actors)
{
	// every time this is called, the NPC executes one action against the world then returns
	// any number of internal objectives may be created, updated, or deleted

	if (i_dont_have(C::AXE_ID) && !im_planning_to_acquire(C::AXE_ID))
	{
		plan_to_get(C::AXE_ID);
	}

	if (i_dont_have(C::SWORD_ID) && !im_planning_to_acquire(C::SWORD_ID))
	{
		plan_to_get(C::SWORD_ID);
	}

	for (deque<Objective>::iterator objective_iterator = objectives.begin();
		objective_iterator != objectives.end();)
	{

		if (objective_iterator->verb == C::AI_OBJECTIVE_ACQUIRE)
		{
			// if the item is here, take it, remove the current objective, and return
			if (world.room_at(x, y, z)->contains_item(objective_iterator->noun))
			{
				take(objective_iterator->noun, world);

				if (objective_iterator->noun == objective_iterator->purpose)
				{
					// this item is an end goal
					erase_objectives_matching_purpose(objective_iterator->purpose);
				}
				else
				{
					// this item is a means to an end
					erase_objective(objective_iterator);
				}

				return;
			}

			// see if the item is reachable
			for (int cx = x - (int)C::VIEW_DISTANCE; cx <= x + (int)C::VIEW_DISTANCE; ++cx)
			{
				for (int cy = y - (int)C::VIEW_DISTANCE; cy <= y + (int)C::VIEW_DISTANCE; ++cy)
				{
					if (!R::bounds_check(cx, cy)) { continue; } // skip if out of bounds

					if (world.room_at(cx, cy, z)->contains_item(objective_iterator->noun))
					{
						if (pathfind(cx, cy, world))
						{
							return;
						}
					}
				}
			}

			// a path could not be found to the item, plan to craft it if it is craftable and the NPC isn't planning to already

			// if i'm not already planning on crafting the item
			// AND the item is craftable
			if (!objective_iterator->already_planning_to_craft
				&& one_can_craft(objective_iterator->noun))
			{
				objective_iterator->already_planning_to_craft = true;
				plan_to_craft(objective_iterator->noun);
				objective_iterator = objectives.begin(); // obligatory reset
				continue; // jump to next iteration
			}
		}

		++objective_iterator;
	}

	for (deque<Objective>::iterator objective_iterator = objectives.begin();
		objective_iterator != objectives.end(); ++objective_iterator)
	{
		// try to craft the item
		const string craft_attempt = craft(objective_iterator->noun, world);
		if (craft_attempt.find("You now have") != string::npos)
		{
			// if successful, clear completed objectives

			if (objective_iterator->noun == objective_iterator->purpose)
			{
				// this item is an end goal
				erase_objectives_matching_purpose(objective_iterator->purpose);
			}
			else
			{
				// this item is a means to an end
				erase_objective(objective_iterator);
			}

			return;
		}
	}

	// the next block: the NPC runs to the first player it finds IF
	// - it is armed with a sword AND
	// - it has no other objectives
	if (i_have(C::SWORD_ID) && objectives.size() == 0) // hardcoding this bit for now
	{
		// for each row in view distance
		for (int cx = x - (int)C::VIEW_DISTANCE; cx <= x + (int)C::VIEW_DISTANCE; ++cx)
		{
			// for each room in the row in view distance
			for (int cy = y - (int)C::VIEW_DISTANCE; cy <= y + (int)C::VIEW_DISTANCE; ++cy)
			{
				// skip this room if it is out of bounds
				if (!R::bounds_check(cx, cy)) { continue; }

				// for each actor in the room
				for (const string & actor_ID : world.room_at(cx, cy, z)->get_actor_ids())
				{
					// if the character is the type of character we're looking for
					if (R::is<PC>(actors.find(actor_ID)->second))
					{
						// cout << endl << actor_ID << " is a player character at " << cx << "," << cy << ". [exterminate! exterminate!]\n";
						// [target acquired]
						pathfind(cx, cy, world);
						return;
					}
				}
			}
		}
	}

}
<commit_msg>improve item acquisition and crafting AI<commit_after>/* Jim Viebke
Jun 3 2015 */

#include "npc_enemy.h"

void Hostile_NPC::update(World & world, map<string, shared_ptr<Character>> & actors)
{
	// Every time this is called, the NPC executes one action against the world then returns.
	// Any number of internal objectives may be created, updated, or deleted.

	if (i_dont_have(C::AXE_ID) && !im_planning_to_acquire(C::AXE_ID))
	{
		plan_to_get(C::AXE_ID);
	}

	if (i_dont_have(C::SWORD_ID) && !im_planning_to_acquire(C::SWORD_ID))
	{
		plan_to_get(C::SWORD_ID);
	}

	// in this block: take the item if it's here, move to the item if it is visible and reachable,
	for (deque<Objective>::iterator objective_iterator = objectives.begin();
		objective_iterator != objectives.end();)
	{

		if (objective_iterator->verb == C::AI_OBJECTIVE_ACQUIRE)
		{
			// if the item is here, take it, remove the current objective, and return
			if (world.room_at(x, y, z)->contains_item(objective_iterator->noun))
			{
				take(objective_iterator->noun, world);

				if (objective_iterator->noun == objective_iterator->purpose)
				{
					// this item is an end goal
					erase_objectives_matching_purpose(objective_iterator->purpose); // erasing all objectives
				}
				else
				{
					// this item is a means to an end
					erase_objective(objective_iterator);
				}

				return;
			}

			// see if the item is reachable
			if (pathfind_to_closest_item(objective_iterator->noun, world))
			{
				return;
			}

			// what's the difference between the above and below block?

			/*for (int cx = x - (int)C::VIEW_DISTANCE; cx <= x + (int)C::VIEW_DISTANCE; ++cx)
			{
			for (int cy = y - (int)C::VIEW_DISTANCE; cy <= y + (int)C::VIEW_DISTANCE; ++cy)
			{
			if (!R::bounds_check(cx, cy)) { continue; } // skip if out of bounds

			if (world.room_at(cx, cy, z)->contains_item(objective_iterator->noun))
			{
			if (pathfind(cx, cy, world))
			{
			return;
			}
			}
			}
			}*/

			// a path could not be found to the item, plan to craft it if it is craftable and the NPC isn't planning to already

			// if i'm not already planning on crafting the item
			// AND the item is craftable
			if (!objective_iterator->already_planning_to_craft
				&& one_can_craft(objective_iterator->noun))
			{
				objective_iterator->already_planning_to_craft = true;
				plan_to_craft(objective_iterator->noun);
				objective_iterator = objectives.begin(); // obligatory reset
				continue; // jump to next iteration
			}
		}

		// if I am planning on moving to an instance
		if (objective_iterator->verb == C::AI_OBJECTIVE_GOTO)
		{
			if (one_can_craft(objective_iterator->purpose) && i_have_all_ingredients_to_craft(objective_iterator->purpose))
			{
				if (pathfind_to_closest_item(objective_iterator->noun, world))
				{
					// delete extra objectives here
					// or maybe not; perhaps the objective should be cleared when the item is taken/crafted

					return;
				}
			}
		}

		++objective_iterator;
	}

	// the next block: work through all objectives, see which objectives can be resolved through crafting attemps.
	for (deque<Objective>::iterator objective_iterator = objectives.begin();
		objective_iterator != objectives.end(); ++objective_iterator)
	{
		// try to craft the item, using obj->purpose if the (obj->verb == GOTO), else use obj->noun (most cases)
		const string craft_attempt = craft(((objective_iterator->verb == C::AI_OBJECTIVE_GOTO) ? objective_iterator->purpose : objective_iterator->noun), world);
		// const string craft_attempt = craft(objective_iterator->noun, world);
		if (craft_attempt.find("You now have") != string::npos)
		{
			// if successful, clear completed objectives

			if (objective_iterator->verb == C::AI_OBJECTIVE_GOTO)
			{
				// the item crafted was from a "goto" objective

				// save this because our firse erase will invalidate the iterator
				const string PURPOSE = objective_iterator->purpose;

				// erase the "goto"
				erase_goto_objective_matching(PURPOSE);

				// erase the "aquire"
				erase_acquire_objective_matching(PURPOSE);
			}
			else if (objective_iterator->noun == objective_iterator->purpose)
			{
				// this item is an end goal
				erase_objectives_matching_purpose(objective_iterator->purpose);
			}
			else
			{
				// this item is only a means to an end
				erase_objective(objective_iterator);
			}

			return;
		}
	}

	// the next block: the NPC runs to the first player it finds IF
	// - it has completed crafting the sword and the axe and has completed all other objectives
	if (i_have(C::SWORD_ID) && i_have(C::AXE_ID) && objectives.size() == 0)
	{
		// for each row in view distance
		for (int cx = x - (int)C::VIEW_DISTANCE; cx <= x + (int)C::VIEW_DISTANCE; ++cx)
		{
			// for each room in the row in view distance
			for (int cy = y - (int)C::VIEW_DISTANCE; cy <= y + (int)C::VIEW_DISTANCE; ++cy)
			{
				// skip this room if it is out of bounds
				if (!R::bounds_check(cx, cy)) { continue; }

				// for each actor in the room
				for (const string & actor_ID : world.room_at(cx, cy, z)->get_actor_ids())
				{
					// if the character is a player character
					if (R::is<PC>(actors.find(actor_ID)->second))
					{
						// [target acquired]
						pathfind(cx, cy, world);
						return;
					}
				}
			}
		}
	}

}
<|endoftext|>


<commit_before>#include "wiVersion.h"

#include <sstream>

namespace wiVersion
{
	// main engine core
	const int major = 0;
	// minor features, major updates
	const int minor = 18;
	// minor bug fixes, alterations, refactors, updates
	const int revision = 8;

	long GetVersion()
	{
		return major * 1000000 + minor * 1000 + revision;
	}
	int GetMajor()
	{
		return major;
	}
	int GetMinor()
	{
		return minor;
	}
	int GetRevision()
	{
		return revision;
	}
	std::string GetVersionString()
	{
		std::stringstream ss("");
		ss << GetMajor() << "." << GetMinor() << "." << GetRevision();
		return ss.str();
	}

}
<commit_msg>changed version number after big graphics device update<commit_after>#include "wiVersion.h"

#include <sstream>

namespace wiVersion
{
	// main engine core
	const int major = 0;
	// minor features, major updates
	const int minor = 19;
	// minor bug fixes, alterations, refactors, updates
	const int revision = 0;

	long GetVersion()
	{
		return major * 1000000 + minor * 1000 + revision;
	}
	int GetMajor()
	{
		return major;
	}
	int GetMinor()
	{
		return minor;
	}
	int GetRevision()
	{
		return revision;
	}
	std::string GetVersionString()
	{
		std::stringstream ss("");
		ss << GetMajor() << "." << GetMinor() << "." << GetRevision();
		return ss.str();
	}

}
<|endoftext|>


<commit_before>#include <iostream>

int main()
{
	printf("Hello World!\n");
}<commit_msg>Fixed the invalid input section<commit_after>#include <iostream>
#include <stdio.h>

unsigned long Fabonacci_Lookup[31] =
{
0,
1,
1,
2,
3,
5,
8,
13,
21,
34,
55,
89,
144,
233,
377,
610,
987,
1597,
2584,
4181,
6765,
10946,
17711,
28657,
46368,
75025,
121393,
196418,
317811,
514229,
832040
};

using namespace std;

int main()
{
	unsigned input;
	while (true)
	{
		cout << "\n\nEnter a number between 0 - 30\n";
		cout << "Program will give back a Fibonacci answer that corresponds\n";
		cout << "to that given number (index): ";

		// scanf_s("%d", &input);
		cin >> input;
		if (!cin)
		{
			cout.flush();
			cin.clear();	// Clear out all failbit flags
			cin.ignore(INT_MAX, '\n'); // Ignore all corrupted input until the next Newline
			cout << "Invalid input.\n";
			continue;
		}

		if ((input < 0) || (input > 30))
		{
			printf("Enter a number between 0 - 31 only.\n");
			continue;
		}

		// Search the lookup table
	printf("The fibonacci number for the given number is: %u\n",
			Fabonacci_Lookup[input]);
	printf("Press Ctrl-C to quit.\n");
	}

}<|endoftext|>


<commit_before>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include "gtest/gtest.h"
#include "Common.h"
#include "Statistics.h"
#include "BitcoinUtils.h"

////////////////////////////////  StatsWindow  /////////////////////////////////
TEST(StatsWindow, clear) {
  int windowSize = 60;

  for (int j = 0; j < 10; j++) {
    StatsWindow<int64> sw(windowSize);
    ASSERT_EQ(sw.sum(windowSize - 1, windowSize), 0);

    int64 val = 3;
    for (int i = 0; i < windowSize; i++) {
      sw.insert(i, val);
    }
    ASSERT_EQ(sw.sum(windowSize - 1, windowSize), windowSize * val);

    sw.clear();
    ASSERT_EQ(sw.sum(windowSize - 1, windowSize), 0);
  }
}

TEST(StatsWindow, sum01) {
  int windowSize = 60;
  StatsWindow<int64> sw(windowSize);
  int64 val = 5;

  for (int i = 0; i < windowSize; i++) {
    sw.insert(i, val);
  }

  for (int i = 0; i < windowSize; i++) {
    ASSERT_EQ(sw.sum(i, 1), val);
  }
  for (int i = 0; i < windowSize; i++) {
    ASSERT_EQ(sw.sum(windowSize - 1, i), i * val);
  }

  for (int i = windowSize; i < windowSize*2; i++) {
    ASSERT_EQ(sw.sum(i, 1), 0);
  }
  for (int i = windowSize; i < windowSize*2; i++) {
    ASSERT_EQ(sw.sum(i, windowSize), (windowSize - (i % windowSize + 1)) * val);
  }

  for (int i = windowSize*2; i < windowSize*3; i++) {
    ASSERT_EQ(sw.sum(i, windowSize), 0);
  }
}

TEST(StatsWindow, sum02) {
  int windowSize = 60;
  StatsWindow<int64> sw(windowSize);
  int64 val = 5;

  for (int i = windowSize - 1; i >= 0; i--) {
    sw.insert(i, val);
  }

  for (int i = 0; i < windowSize; i++) {
    ASSERT_EQ(sw.sum(i, 1), val);
  }
  for (int i = 0; i < windowSize; i++) {
    ASSERT_EQ(sw.sum(windowSize - 1, i), i * val);
  }

  for (int i = windowSize; i < windowSize*2; i++) {
    ASSERT_EQ(sw.sum(i, 1), 0);
  }
  for (int i = windowSize; i < windowSize*2; i++) {
    ASSERT_EQ(sw.sum(i, windowSize), (windowSize - (i % windowSize + 1)) * val);
  }

  for (int i = windowSize*2; i < windowSize*3; i++) {
    ASSERT_EQ(sw.sum(i, windowSize), 0);
  }
}

TEST(StatsWindow, sum03) {
  StatsWindow<int64> sw(5);
  sw.insert(0, 1);
  ASSERT_EQ(sw.sum(0, 1), 1);
  sw.clear();
  ASSERT_EQ(sw.sum(0, 1), 0);

  sw.insert(0, 1);
  sw.insert(5, 5);
  ASSERT_EQ(sw.sum(5, 1), 5);
  ASSERT_EQ(sw.sum(5, 5), 5);
  sw.clear();

  sw.insert(0, 1);
  sw.insert(1, 2);
  sw.insert(2, 3);
  sw.insert(3, 4);
  sw.insert(4, 5);
  ASSERT_EQ(sw.sum(4, 1), 5);
  ASSERT_EQ(sw.sum(4, 2), 9);
  ASSERT_EQ(sw.sum(4, 3), 12);
  ASSERT_EQ(sw.sum(4, 4), 14);
  ASSERT_EQ(sw.sum(4, 5), 15);

  sw.insert(8, 9);
  ASSERT_EQ(sw.sum(8, 5), 14);
  sw.insert(7, 8);
  ASSERT_EQ(sw.sum(8, 5), 22);
  sw.insert(6, 7);
  ASSERT_EQ(sw.sum(8, 5), 29);
  sw.insert(5, 6);
  ASSERT_EQ(sw.sum(8, 5), 35);
}

TEST(StatsWindow, map) {
  int windowSize = 10;
  StatsWindow<int64> sw(windowSize);
  for (int i = 0; i < windowSize; i++) {
    sw.insert(i, i * 2);
  }
  ASSERT_EQ(sw.sum(windowSize-1), sw.sum(windowSize-1, windowSize));

  int64 sum = sw.sum(windowSize-1, windowSize);
  sw.mapDivide(2);
  int64 sum2 = sw.sum(windowSize-1, windowSize);
  ASSERT_EQ(sum/2, sum2);

  sw.mapMultiply(2);
  int64 sum3 = sw.sum(windowSize-1, windowSize);
  ASSERT_EQ(sum, sum3);
}

////////////////////////////////  ShareStatsDay  ///////////////////////////////
TEST(ShareStatsDay, ShareStatsDay) {
  // using mainnet
  SelectParams(CBaseChainParams::MAIN);

  // 1
  {
    ShareStatsDay<ShareBitcoin> stats;
    ShareBitcoin share;

    share.height_ = 504031;
    share.status_ = StratumStatus::ACCEPT;
    uint64_t shareValue = 1ll;

    auto reward = GetBlockReward(share.height_, Params().GetConsensus());

    // share -> socre = 1 : 1
    // https://btc.com/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
    share.blkBits_ = 0x1d00ffffu;

    // accept
    for (uint32_t i = 0; i < 24; i++) {  // hour idx range: [0, 23]
      share.shareDiff_ = shareValue;
      stats.processShare(i, share);
    }

    // reject
    share.status_ = StratumStatus::REJECT_NO_REASON;
    for (uint32_t i = 0; i < 24; i++) {
      share.shareDiff_ = shareValue;
      stats.processShare(i, share);
    }

    ShareStats ss;
    for (uint32_t i = 0; i < 24; i++) {
      stats.getShareStatsHour(i, &ss);
      ASSERT_EQ(ss.shareAccept_, shareValue);
      ASSERT_EQ(ss.shareReject_, shareValue);
      ASSERT_EQ(ss.earn_, 1 * reward);
    }
    stats.getShareStatsDay(&ss);
    ASSERT_EQ(ss.shareAccept_, shareValue * 24);
    ASSERT_EQ(ss.shareReject_, shareValue * 24);
    ASSERT_EQ(ss.earn_, 1 * 24 * reward);
  }

  // UINT32_MAX
  {
    ShareStatsDay<ShareBitcoin> stats;
    ShareBitcoin share;

    share.height_ = 504031;
    share.status_  = StratumStatus::ACCEPT;
    uint64_t shareValue = UINT32_MAX;

    // share -> socre = UINT32_MAX : 0.0197582875516673
    // https://btc.com/00000000000000000015f613f161b431acc6bbcb34533d2ca47d3cde4ec58b76
    share.blkBits_ = 0x18050edcu;

    // accept
    for (uint32_t i = 0; i < 24; i++) {  // hour idx range: [0, 23]
      share.shareDiff_ = shareValue;
      stats.processShare(i, share);
//      LOG(INFO) << score2Str(share.score());
    }

    // reject
    share.status_ = StratumStatus::REJECT_NO_REASON;
    for (uint32_t i = 0; i < 24; i++) {
      share.shareDiff_ = shareValue;
      stats.processShare(i, share);
    }

    ShareStats ss;
    for (uint32_t i = 0; i < 24; i++) {
      stats.getShareStatsHour(i, &ss);
      ASSERT_EQ(ss.shareAccept_, shareValue);
      ASSERT_EQ(ss.shareReject_, shareValue);

      #ifndef CHAIN_TYPE_UBTC
        ASSERT_EQ((uint64_t)ss.earn_, 24697859);  // satoshi
      #else
        ASSERT_EQ((uint64_t)ss.earn_, 1975828);  // satoshi, only for UBTC
      #endif
    }
    stats.getShareStatsDay(&ss);
    ASSERT_EQ(ss.shareAccept_, shareValue * 24);
    ASSERT_EQ(ss.shareReject_, shareValue * 24);
    #ifndef CHAIN_TYPE_UBTC
      ASSERT_EQ((uint64_t)ss.earn_, 592748626);  // satoshi
    #else
      ASSERT_EQ((uint64_t)ss.earn_, 47419890);  // satoshi, only for UBTC
    #endif
  }
}
<commit_msg>testcase: fix build warning.<commit_after>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include "gtest/gtest.h"
#include "Common.h"
#include "Statistics.h"
#include "BitcoinUtils.h"

////////////////////////////////  StatsWindow  /////////////////////////////////
TEST(StatsWindow, clear) {
  int windowSize = 60;

  for (int j = 0; j < 10; j++) {
    StatsWindow<int64> sw(windowSize);
    ASSERT_EQ(sw.sum(windowSize - 1, windowSize), 0);

    int64 val = 3;
    for (int i = 0; i < windowSize; i++) {
      sw.insert(i, val);
    }
    ASSERT_EQ(sw.sum(windowSize - 1, windowSize), windowSize * val);

    sw.clear();
    ASSERT_EQ(sw.sum(windowSize - 1, windowSize), 0);
  }
}

TEST(StatsWindow, sum01) {
  int windowSize = 60;
  StatsWindow<int64> sw(windowSize);
  int64 val = 5;

  for (int i = 0; i < windowSize; i++) {
    sw.insert(i, val);
  }

  for (int i = 0; i < windowSize; i++) {
    ASSERT_EQ(sw.sum(i, 1), val);
  }
  for (int i = 0; i < windowSize; i++) {
    ASSERT_EQ(sw.sum(windowSize - 1, i), i * val);
  }

  for (int i = windowSize; i < windowSize*2; i++) {
    ASSERT_EQ(sw.sum(i, 1), 0);
  }
  for (int i = windowSize; i < windowSize*2; i++) {
    ASSERT_EQ(sw.sum(i, windowSize), (windowSize - (i % windowSize + 1)) * val);
  }

  for (int i = windowSize*2; i < windowSize*3; i++) {
    ASSERT_EQ(sw.sum(i, windowSize), 0);
  }
}

TEST(StatsWindow, sum02) {
  int windowSize = 60;
  StatsWindow<int64> sw(windowSize);
  int64 val = 5;

  for (int i = windowSize - 1; i >= 0; i--) {
    sw.insert(i, val);
  }

  for (int i = 0; i < windowSize; i++) {
    ASSERT_EQ(sw.sum(i, 1), val);
  }
  for (int i = 0; i < windowSize; i++) {
    ASSERT_EQ(sw.sum(windowSize - 1, i), i * val);
  }

  for (int i = windowSize; i < windowSize*2; i++) {
    ASSERT_EQ(sw.sum(i, 1), 0);
  }
  for (int i = windowSize; i < windowSize*2; i++) {
    ASSERT_EQ(sw.sum(i, windowSize), (windowSize - (i % windowSize + 1)) * val);
  }

  for (int i = windowSize*2; i < windowSize*3; i++) {
    ASSERT_EQ(sw.sum(i, windowSize), 0);
  }
}

TEST(StatsWindow, sum03) {
  StatsWindow<int64> sw(5);
  sw.insert(0, 1);
  ASSERT_EQ(sw.sum(0, 1), 1);
  sw.clear();
  ASSERT_EQ(sw.sum(0, 1), 0);

  sw.insert(0, 1);
  sw.insert(5, 5);
  ASSERT_EQ(sw.sum(5, 1), 5);
  ASSERT_EQ(sw.sum(5, 5), 5);
  sw.clear();

  sw.insert(0, 1);
  sw.insert(1, 2);
  sw.insert(2, 3);
  sw.insert(3, 4);
  sw.insert(4, 5);
  ASSERT_EQ(sw.sum(4, 1), 5);
  ASSERT_EQ(sw.sum(4, 2), 9);
  ASSERT_EQ(sw.sum(4, 3), 12);
  ASSERT_EQ(sw.sum(4, 4), 14);
  ASSERT_EQ(sw.sum(4, 5), 15);

  sw.insert(8, 9);
  ASSERT_EQ(sw.sum(8, 5), 14);
  sw.insert(7, 8);
  ASSERT_EQ(sw.sum(8, 5), 22);
  sw.insert(6, 7);
  ASSERT_EQ(sw.sum(8, 5), 29);
  sw.insert(5, 6);
  ASSERT_EQ(sw.sum(8, 5), 35);
}

TEST(StatsWindow, map) {
  int windowSize = 10;
  StatsWindow<int64> sw(windowSize);
  for (int i = 0; i < windowSize; i++) {
    sw.insert(i, i * 2);
  }
  ASSERT_EQ(sw.sum(windowSize-1), sw.sum(windowSize-1, windowSize));

  int64 sum = sw.sum(windowSize-1, windowSize);
  sw.mapDivide(2);
  int64 sum2 = sw.sum(windowSize-1, windowSize);
  ASSERT_EQ(sum/2, sum2);

  sw.mapMultiply(2);
  int64 sum3 = sw.sum(windowSize-1, windowSize);
  ASSERT_EQ(sum, sum3);
}

////////////////////////////////  ShareStatsDay  ///////////////////////////////
TEST(ShareStatsDay, ShareStatsDay) {
  // using mainnet
  SelectParams(CBaseChainParams::MAIN);

  // 1
  {
    ShareStatsDay<ShareBitcoin> stats;
    ShareBitcoin share;

    share.height_ = 504031;
    share.status_ = StratumStatus::ACCEPT;
    uint64_t shareValue = 1ll;

    auto reward = GetBlockReward(share.height_, Params().GetConsensus());

    // share -> socre = 1 : 1
    // https://btc.com/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
    share.blkBits_ = 0x1d00ffffu;

    // accept
    for (uint32_t i = 0; i < 24; i++) {  // hour idx range: [0, 23]
      share.shareDiff_ = shareValue;
      stats.processShare(i, share);
    }

    // reject
    share.status_ = StratumStatus::REJECT_NO_REASON;
    for (uint32_t i = 0; i < 24; i++) {
      share.shareDiff_ = shareValue;
      stats.processShare(i, share);
    }

    ShareStats ss;
    for (uint32_t i = 0; i < 24; i++) {
      stats.getShareStatsHour(i, &ss);
      ASSERT_EQ(ss.shareAccept_, shareValue);
      ASSERT_EQ(ss.shareReject_, shareValue);
      ASSERT_EQ(ss.earn_, 1 * reward);
    }
    stats.getShareStatsDay(&ss);
    ASSERT_EQ(ss.shareAccept_, shareValue * 24);
    ASSERT_EQ(ss.shareReject_, shareValue * 24);
    ASSERT_EQ(ss.earn_, 1 * 24 * reward);
  }

  // UINT32_MAX
  {
    ShareStatsDay<ShareBitcoin> stats;
    ShareBitcoin share;

    share.height_ = 504031;
    share.status_  = StratumStatus::ACCEPT;
    uint64_t shareValue = UINT32_MAX;

    // share -> socre = UINT32_MAX : 0.0197582875516673
    // https://btc.com/00000000000000000015f613f161b431acc6bbcb34533d2ca47d3cde4ec58b76
    share.blkBits_ = 0x18050edcu;

    // accept
    for (uint32_t i = 0; i < 24; i++) {  // hour idx range: [0, 23]
      share.shareDiff_ = shareValue;
      stats.processShare(i, share);
//      LOG(INFO) << score2Str(share.score());
    }

    // reject
    share.status_ = StratumStatus::REJECT_NO_REASON;
    for (uint32_t i = 0; i < 24; i++) {
      share.shareDiff_ = shareValue;
      stats.processShare(i, share);
    }

    ShareStats ss;
    for (uint32_t i = 0; i < 24; i++) {
      stats.getShareStatsHour(i, &ss);
      ASSERT_EQ(ss.shareAccept_, shareValue);
      ASSERT_EQ(ss.shareReject_, shareValue);

      #ifndef CHAIN_TYPE_UBTC
        ASSERT_EQ((int64_t)ss.earn_, 24697859);  // satoshi
      #else
        ASSERT_EQ((int64_t)ss.earn_, 1975828);  // satoshi, only for UBTC
      #endif
    }
    stats.getShareStatsDay(&ss);
    ASSERT_EQ(ss.shareAccept_, shareValue * 24);
    ASSERT_EQ(ss.shareReject_, shareValue * 24);
    #ifndef CHAIN_TYPE_UBTC
      ASSERT_EQ((int64_t)ss.earn_, 592748626);  // satoshi
    #else
      ASSERT_EQ((int64_t)ss.earn_, 47419890);  // satoshi, only for UBTC
    #endif
  }
}
<|endoftext|>


<commit_before>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"

#include "entityx/Event.h"
#include "entityx/Entity.h"
#include "entityx/System.h"

#include "pockets/Types.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace entityx;
using pockets::Vertex2d;

struct Locus : Component<Locus>
{
  Locus() = default;
  Locus( const ci::Vec2f &pos, const ci::Vec2f &registration, float rot, shared_ptr<Locus> parent=nullptr ):
  position( pos ),
  registration_point( registration ),
  rotation( rot ),
  parent( parent )
  {}
  ci::Vec2f         position = ci::Vec2f::zero();
  ci::Vec2f         registration_point = ci::Vec2f::zero();
  float             rotation = 0.0f;
  shared_ptr<Locus> parent = nullptr;

  ci::MatrixAffine2f  toMatrix() const{
    MatrixAffine2f mat;
    mat.translate( position + registration_point );
    mat.rotate( rotation );
    mat.translate( -registration_point );
    if( parent ){ mat = parent->toMatrix() * mat; }
    return mat;
  }
};

struct Mesh : Component<Mesh>
{
  Mesh( int render_layer=0, const ci::Rectf &bounds={ -20.0f, -10.0f, 20.0f, 10.0f } ):
  render_layer( render_layer )
  {
    vertices.assign( 4, Vertex2d{} );
    vertices[0].position = bounds.getUpperRight();
    vertices[1].position = bounds.getUpperLeft();
    vertices[2].position = bounds.getLowerRight();
    vertices[3].position = bounds.getLowerLeft();
  }
  std::vector<Vertex2d> vertices;
  int                   render_layer = 0;
};

struct Velocity : Component<Velocity>
{
  Velocity( float x = 0.0f, float y = 0.0f ):
  velocity( x, y )
  {}
  ci::Vec2f velocity;
};

struct MovementSystem : public System<MovementSystem>
{
  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    for( auto entity : es->entities_with_components<Locus>() )
    {
      auto loc = entity.component<Locus>();
      loc->rotation = fmodf( loc->rotation + M_PI * 0.01f, M_PI * 2 );
    }
  }
};

struct RenderSystem : public System<RenderSystem>
{
  typedef pair<shared_ptr<Locus>, shared_ptr<Mesh>> MeshPair;
  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    if( mGeometry.empty() )
    {
      for( auto entity : es->entities_with_components<Locus, Mesh>() )
      {
        mGeometry.emplace_back( entity.component<Locus>(), entity.component<Mesh>() );
      }
      stable_sort( mGeometry.begin(), mGeometry.end(), []( const MeshPair &lhs, const MeshPair &rhs ) -> bool {
        return lhs.second->render_layer < rhs.second->render_layer;
      } );
    }
    // assemble all vertices
    mVertices.clear();
    for( auto pair : mGeometry )
    {
      auto loc = pair.first;
      auto mesh = pair.second;
      auto mat = loc->toMatrix();
      if( !mVertices.empty() )
      { // create degenerate triangle between previous and current shape
        mVertices.emplace_back( mVertices.back() );
        auto vert = mesh->vertices.front();
        mVertices.emplace_back( Vertex2d{ mat.transformPoint( vert.position ), vert.color, vert.tex_coord } );
      }
      for( auto &vert : mesh->vertices )
      {
        mVertices.emplace_back( Vertex2d{ mat.transformPoint( vert.position ), vert.color, vert.tex_coord } );
      }
    }
  }

  void draw()
  {
    glEnableClientState( GL_VERTEX_ARRAY );
    glEnableClientState( GL_COLOR_ARRAY );
    glEnableClientState( GL_TEXTURE_COORD_ARRAY );

    glVertexPointer( 2, GL_FLOAT, sizeof( Vertex2d ), &mVertices[0].position.x );
    glTexCoordPointer( 2, GL_FLOAT, sizeof( Vertex2d ), &mVertices[0].tex_coord.x );
    glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( Vertex2d ), &mVertices[0].color.r );
    glDrawArrays( GL_TRIANGLE_STRIP, 0, mVertices.size() );

    glDisableClientState( GL_VERTEX_ARRAY );
    glDisableClientState( GL_COLOR_ARRAY );
    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
  }
private:
  std::vector<MeshPair> mGeometry;
  std::vector<Vertex2d> mVertices;
};

class PupTentApp : public AppNative
{
public:
	void setup();
	void mouseDown( MouseEvent event );
	void update();
	void draw();
private:
  shared_ptr<EventManager>  mEvents;
  shared_ptr<EntityManager> mEntities;
  shared_ptr<SystemManager> mSystemManager;
  shared_ptr<MovementSystem>  mMovement;
  double mLastUpdate = 0.0;
  double            mAverageRenderTime = 0;
};

void PupTentApp::setup()
{
  mEvents = EventManager::make();
  mEntities = EntityManager::make(mEvents);
  mSystemManager = SystemManager::make( mEntities, mEvents );
  mSystemManager->add<MovementSystem>();
  mSystemManager->add<RenderSystem>();
  mSystemManager->configure();

  Rand r;
  Vec2f center = getWindowCenter();
  for( int i = 0; i < 2000; ++i )
  {
    Entity entity = mEntities->create();
    auto loc = shared_ptr<Locus>{ new Locus };
    auto mesh = shared_ptr<Mesh>{ new Mesh };
    ColorA color{ CM_HSV, r.nextFloat( 1.0f ), 0.9f, 0.9f, 1.0f };
    for( auto &v : mesh->vertices )
    {
      v.color = color;
    }
    loc->position = { r.nextFloat( getWindowWidth() ), r.nextFloat( getWindowHeight() ) };
    loc->rotation = r.nextFloat( M_PI * 2 );
    mesh->render_layer = loc->position.distance( center );
    entity.assign<Locus>( loc );
    entity.assign<Mesh>( mesh );
  }
}

void PupTentApp::mouseDown( MouseEvent event )
{
}

void PupTentApp::update()
{
  double now = getElapsedSeconds();
  double dt = now - mLastUpdate;
  mLastUpdate = now;
//  double start = getElapsedSeconds();
  mSystemManager->update<MovementSystem>( dt );
//  double end = getElapsedSeconds();
//  cout << "Update: " << (end - start) * 1000 << endl;
}

void PupTentApp::draw()
{
	// clear out the window with black
	gl::clear( Color( 0, 0, 0 ) );
  double start = getElapsedSeconds();
  mSystemManager->update<RenderSystem>( 0.0 );
  mSystemManager->system<RenderSystem>()->draw();
  double end = getElapsedSeconds();
  double ms = (end - start) * 1000;
  mAverageRenderTime = (mAverageRenderTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 120 == 0 )
  {
    cout << "Render ms: " << mAverageRenderTime << endl;
  }
}

CINDER_APP_NATIVE( PupTentApp, RendererGl )

<commit_msg>Cacheing update query as well.<commit_after>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"

#include "entityx/Event.h"
#include "entityx/Entity.h"
#include "entityx/System.h"

#include "pockets/Types.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace entityx;
using pockets::Vertex2d;

struct Locus : Component<Locus>
{
  Locus() = default;
  Locus( const ci::Vec2f &pos, const ci::Vec2f &registration, float rot, shared_ptr<Locus> parent=nullptr ):
  position( pos ),
  registration_point( registration ),
  rotation( rot ),
  parent( parent )
  {}
  ci::Vec2f         position = ci::Vec2f::zero();
  ci::Vec2f         registration_point = ci::Vec2f::zero();
  float             rotation = 0.0f;
  shared_ptr<Locus> parent = nullptr;

  ci::MatrixAffine2f  toMatrix() const{
    MatrixAffine2f mat;
    mat.translate( position + registration_point );
    mat.rotate( rotation );
    mat.translate( -registration_point );
    if( parent ){ mat = parent->toMatrix() * mat; }
    return mat;
  }
};

struct Mesh : Component<Mesh>
{
  Mesh( int render_layer=0, const ci::Rectf &bounds={ -20.0f, -10.0f, 20.0f, 10.0f } ):
  render_layer( render_layer )
  {
    vertices.assign( 4, Vertex2d{} );
    vertices[0].position = bounds.getUpperRight();
    vertices[1].position = bounds.getUpperLeft();
    vertices[2].position = bounds.getLowerRight();
    vertices[3].position = bounds.getLowerLeft();
  }
  std::vector<Vertex2d> vertices;
  int                   render_layer = 0;
};

struct Velocity : Component<Velocity>
{
  Velocity( float x = 0.0f, float y = 0.0f ):
  velocity( x, y )
  {}
  ci::Vec2f velocity;
};

struct MovementSystem : public System<MovementSystem>
{
  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    if( mElements.empty() )
    {
      for( auto entity : es->entities_with_components<Locus>() )
      {
        mElements.push_back( entity.component<Locus>() );
      }
    }
    for( auto& loc : mElements )
    {
      loc->rotation = fmodf( loc->rotation + M_PI * 0.01f, M_PI * 2 );
    }
  }

  vector<shared_ptr<Locus>> mElements;
};

/**
 Basic layer-sorted rendering system
*/
struct RenderSystem : public System<RenderSystem>, Receiver<RenderSystem>
{
  typedef pair<shared_ptr<Locus>, shared_ptr<Mesh>> MeshPair;

  void configure( EventManager &event_manager )
  {
    event_manager.subscribe<EntityDestroyedEvent>( *this );
    event_manager.subscribe<ComponentAddedEvent<Mesh>>( *this );
  }

  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    // build our sorted geometry list from query if the layers/components have changed
    // need to rebuild if any meshes are removed or added
    if( mGeometry.empty() )
    {
      for( auto entity : es->entities_with_components<Locus, Mesh>() )
      {
        mGeometry.emplace_back( entity.component<Locus>(), entity.component<Mesh>() );
      }
      stable_sort( mGeometry.begin(), mGeometry.end(), []( const MeshPair &lhs, const MeshPair &rhs ) -> bool {
        return lhs.second->render_layer < rhs.second->render_layer;
      } );
    }
    // assemble all vertices
    mVertices.clear();
    for( auto pair : mGeometry )
    {
      auto loc = pair.first;
      auto mesh = pair.second;
      auto mat = loc->toMatrix();
      if( !mVertices.empty() )
      { // create degenerate triangle between previous and current shape
        mVertices.emplace_back( mVertices.back() );
        auto vert = mesh->vertices.front();
        mVertices.emplace_back( Vertex2d{ mat.transformPoint( vert.position ), vert.color, vert.tex_coord } );
      }
      for( auto &vert : mesh->vertices )
      {
        mVertices.emplace_back( Vertex2d{ mat.transformPoint( vert.position ), vert.color, vert.tex_coord } );
      }
    }
  }

  void receive( const EntityDestroyedEvent &event )
  {
    auto entity = event.entity;
    if( entity.component<Mesh>() )
    { // if a mesh was destroyed, we will update our render list this frame
      mGeometry.clear();
    }
  }

  void receive( const ComponentAddedEvent<Mesh> &event )
  { // empty our geometry
    mGeometry.clear();
  }

  void draw()
  {
    glEnableClientState( GL_VERTEX_ARRAY );
    glEnableClientState( GL_COLOR_ARRAY );
    glEnableClientState( GL_TEXTURE_COORD_ARRAY );

    glVertexPointer( 2, GL_FLOAT, sizeof( Vertex2d ), &mVertices[0].position.x );
    glTexCoordPointer( 2, GL_FLOAT, sizeof( Vertex2d ), &mVertices[0].tex_coord.x );
    glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( Vertex2d ), &mVertices[0].color.r );
    glDrawArrays( GL_TRIANGLE_STRIP, 0, mVertices.size() );

    glDisableClientState( GL_VERTEX_ARRAY );
    glDisableClientState( GL_COLOR_ARRAY );
    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
  }
private:
  std::vector<MeshPair> mGeometry;
  std::vector<Vertex2d> mVertices;
};

class PupTentApp : public AppNative
{
public:
	void setup();
	void mouseDown( MouseEvent event );
	void update();
	void draw();
private:
  shared_ptr<EventManager>  mEvents;
  shared_ptr<EntityManager> mEntities;
  shared_ptr<SystemManager> mSystemManager;
  shared_ptr<MovementSystem>  mMovement;
  double mLastUpdate = 0.0;
  double            mAverageRenderTime = 0;
};

void PupTentApp::setup()
{
  mEvents = EventManager::make();
  mEntities = EntityManager::make(mEvents);
  mSystemManager = SystemManager::make( mEntities, mEvents );
  mSystemManager->add<MovementSystem>();
  mSystemManager->add<RenderSystem>();
  mSystemManager->configure();

  Rand r;
  Vec2f center = getWindowCenter();
  for( int i = 0; i < 50000; ++i )
  {
    Entity entity = mEntities->create();
    auto loc = shared_ptr<Locus>{ new Locus };
    auto mesh = shared_ptr<Mesh>{ new Mesh };
    ColorA color{ CM_HSV, r.nextFloat( 1.0f ), 0.9f, 0.9f, 1.0f };
    for( auto &v : mesh->vertices )
    {
      v.color = color;
    }
    loc->position = { r.nextFloat( getWindowWidth() ), r.nextFloat( getWindowHeight() ) };
    loc->rotation = r.nextFloat( M_PI * 2 );
    mesh->render_layer = loc->position.distance( center );
    entity.assign<Locus>( loc );
    entity.assign<Mesh>( mesh );
  }
}

void PupTentApp::mouseDown( MouseEvent event )
{}

void PupTentApp::update()
{
  double now = getElapsedSeconds();
  double dt = now - mLastUpdate;
  mLastUpdate = now;
  double start = getElapsedSeconds();
  mSystemManager->update<MovementSystem>( dt );
  double end = getElapsedSeconds();
  if( getElapsedFrames() % 120 == 0 )
  {
    cout << "Update: " << (end - start) * 1000 << endl;
  }
}

void PupTentApp::draw()
{
	// clear out the window with black
	gl::clear( Color( 0, 0, 0 ) );
  double start = getElapsedSeconds();
  mSystemManager->update<RenderSystem>( 0.0 );
  mSystemManager->system<RenderSystem>()->draw();
  double end = getElapsedSeconds();
  double ms = (end - start) * 1000;
  mAverageRenderTime = (mAverageRenderTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 120 == 0 )
  {
    cout << "Render ms: " << mAverageRenderTime << endl;
  }
}

CINDER_APP_NATIVE( PupTentApp, RendererGl )

<|endoftext|>


<commit_before>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"
#include "cinder/Json.h"
#include "cinder/ip/Premultiply.h"

#include "entityx/Event.h"
#include "entityx/Entity.h"
#include "entityx/System.h"

#include "puptent/BatchRenderSystem2d.h"
#include "puptent/PhysicsSystem2d.h"
#include "puptent/TextureAtlas.h"
#include "puptent/SpriteAnimation.h"

/**
 Sample app used to develop features of PupTent.
 Learning about component systems and building my own components.
 While everything is dependent on the underlying component machinery,
 it is wonderfully decoupled from other systems and components.
*/

using namespace ci;
using namespace ci::app;
using namespace std;
using namespace puptent;

using namespace entityx;
using pockets::Vertex2d;

struct MovementSystem : public System<MovementSystem>
{
  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    if( mElements.empty() )
    {
      for( auto entity : es->entities_with_components<Locus>() )
      {
        mElements.push_back( entity.component<Locus>() );
      }
    }
    time += dt;
    for( auto& loc : mElements )
    {
      loc->rotation = fmodf( loc->rotation - M_PI * 0.01f, M_PI * 2 );
      loc->scale = math<float>::sin( 0.5f * time + M_PI * loc->position.x / 640.0f + M_PI * loc->position.y / 480.0f );
    }
  }
  double time = 0.0;
  vector<shared_ptr<Locus>> mElements;
};

class PupTentApp : public AppNative
{
public:
  void prepareSettings( Settings *settings );
	void setup();
	void update();
	void draw();
private:
  shared_ptr<EventManager>  mEvents;
  shared_ptr<EntityManager> mEntities;
  shared_ptr<SystemManager> mSystemManager;
  double                    mAverageUpdateTime = 1.0;
  double                    mAverageRenderTime = 1.0;
  Timer                     mTimer;
  TextureAtlas              mTextureAtlas;
};

void PupTentApp::prepareSettings( Settings *settings )
{
  settings->disableFrameRate();
  settings->setWindowSize( 1024, 768 );
//  settings->setFullScreen();
}

void PupTentApp::setup()
{
  gl::enableVerticalSync();
  Surface sprite_surf{ loadImage( loadAsset( "spritesheet.png" ) ) };
  if( !sprite_surf.isPremultiplied() )
  {
    ip::premultiply( &sprite_surf );
  }
  TextureAtlasRef atlas = TextureAtlas::create( sprite_surf, JsonTree( loadAsset( "spritesheet.json" ) ) );
  JsonTree animations{ loadAsset( "animations.json" ) };

  mEvents = EventManager::make();
  mEntities = EntityManager::make(mEvents);
  mSystemManager = SystemManager::make( mEntities, mEvents );
  mSystemManager->add<MovementSystem>();
  auto physics = mSystemManager->add<PhysicsSystem2d>();
  physics->createBoundaryRect( getWindowBounds() );
  auto renderer = mSystemManager->add<BatchRenderSystem2d>();
  renderer->setTexture( atlas->getTexture() );
  shared_ptr<SpriteAnimationSystem> sprite_system{ new SpriteAnimationSystem{ atlas, animations } };
  mSystemManager->add( sprite_system );
  mSystemManager->configure();

  Rand r;
  Vec2f center = getWindowCenter();
  Entity entity;
  for( int i = 0; i < 8000; ++i )
  {
    entity = mEntities->create();
    auto loc = shared_ptr<Locus>{ new Locus };
    // get an animation out of the sprite system
    auto anim = sprite_system->createSpriteAnimation( "dot" );
    loc->position = { r.nextFloat( getWindowWidth() ), r.nextFloat( getWindowHeight() ) };
    loc->rotation = r.nextFloat( M_PI * 2 );
    loc->registration_point = { 0, 0 };
    float dist = loc->position.distance( center );
    ColorA color{ CM_HSV, 0.0f, 0.0f, lmap( dist, 0.0f, 0.75f * getWindowWidth(), 0.0f, 1.0f ), 1.0f };
//    entity.assign( physics->createBox( loc->position, atlas->get( "d-0001" ).size / 12.0f, loc->rotation ) );
    auto mesh = entity.assign<RenderMesh2d>( 4, dist );
    for( auto &v : mesh->vertices )
    {
      v.color = color;
    }
    entity.assign( anim );
    entity.assign( loc );
  }

  getWindow()->getSignalMouseDown().connect( [=]( MouseEvent &event ) mutable
  {
    if( entity.valid() )
    {
      if( entity.component<SpriteAnimation>() )
      {
        cout << "Removing Sprite Animation component: " << entity << endl;
        entity.remove<SpriteAnimation>();
      }
      else
      {
        cout << "Adding Mesh component: " << entity << endl;
        auto mesh = RenderMesh2dRef{ new RenderMesh2d{ 4 } };
        // perhaps have a component to hang on to texturing data
        mesh->setAsTexture( atlas->get( "dl-0001" ) );
        mesh->render_layer = 1000;
        ColorA color{ 1.0f, 1.0f, 1.0f, 1.0f };
        for( auto &v : mesh->vertices )
        {
          v.color = color;
        }
        entity.assign<RenderMesh2d>( mesh );
      }
    }
  });

  mTimer.start();
}

void PupTentApp::update()
{
  double dt = mTimer.getSeconds();
  mTimer.start();
  Timer up;
  up.start();
  mSystemManager->system<PhysicsSystem2d>()->stepPhysics(); // could parallelize this with sprite animation and some other things...
  mSystemManager->update<PhysicsSystem2d>( dt );
  mSystemManager->update<MovementSystem>( dt );
  mSystemManager->update<SpriteAnimationSystem>( dt );
  mSystemManager->update<BatchRenderSystem2d>( dt );
  double ms = up.getSeconds() * 1000;
  mAverageUpdateTime = (mAverageUpdateTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Update: " << mAverageUpdateTime << ", " << ms << endl;
  }
}

void PupTentApp::draw()
{
	gl::clear( Color::black() );
  gl::disableDepthRead();
  gl::disableDepthWrite();
  gl::color( Color::white() );
  Timer dr;
  dr.start();
  mSystemManager->system<BatchRenderSystem2d>()->draw();
//  mSystemManager->system<PhysicsSystem2d>()->debugDraw();
  double ms = dr.getSeconds() * 1000;
  mAverageRenderTime = (mAverageRenderTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Render ms: " << mAverageRenderTime << ", " << ms << endl;
  }
}

CINDER_APP_NATIVE( PupTentApp, RendererGl( RendererGl::AA_MSAA_8 ) )

<commit_msg>10k entities.<commit_after>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"
#include "cinder/Json.h"
#include "cinder/ip/Premultiply.h"

#include "entityx/Event.h"
#include "entityx/Entity.h"
#include "entityx/System.h"

#include "puptent/BatchRenderSystem2d.h"
#include "puptent/PhysicsSystem2d.h"
#include "puptent/TextureAtlas.h"
#include "puptent/SpriteAnimation.h"

/**
 Sample app used to develop features of PupTent.
 Learning about component systems and building my own components.
 While everything is dependent on the underlying component machinery,
 it is wonderfully decoupled from other systems and components.
*/

using namespace ci;
using namespace ci::app;
using namespace std;
using namespace puptent;

using namespace entityx;
using pockets::Vertex2d;

struct MovementSystem : public System<MovementSystem>
{
  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    if( mElements.empty() )
    {
      for( auto entity : es->entities_with_components<Locus>() )
      {
        mElements.push_back( entity.component<Locus>() );
      }
    }
    time += dt;
    for( auto& loc : mElements )
    {
      loc->rotation = fmodf( loc->rotation - M_PI * 0.01f, M_PI * 2 );
      loc->scale = math<float>::sin( 0.5f * time + M_PI * loc->position.x / 640.0f + M_PI * loc->position.y / 480.0f );
    }
  }
  double time = 0.0;
  vector<shared_ptr<Locus>> mElements;
};

class PupTentApp : public AppNative
{
public:
  void prepareSettings( Settings *settings );
	void setup();
	void update();
	void draw();
private:
  shared_ptr<EventManager>  mEvents;
  shared_ptr<EntityManager> mEntities;
  shared_ptr<SystemManager> mSystemManager;
  double                    mAverageUpdateTime = 1.0;
  double                    mAverageRenderTime = 1.0;
  Timer                     mTimer;
  TextureAtlas              mTextureAtlas;
};

void PupTentApp::prepareSettings( Settings *settings )
{
  settings->disableFrameRate();
  settings->setWindowSize( 1024, 768 );
//  settings->setFullScreen();
}

void PupTentApp::setup()
{
  gl::enableVerticalSync();
  Surface sprite_surf{ loadImage( loadAsset( "spritesheet.png" ) ) };
  if( !sprite_surf.isPremultiplied() )
  {
    ip::premultiply( &sprite_surf );
  }
  TextureAtlasRef atlas = TextureAtlas::create( sprite_surf, JsonTree( loadAsset( "spritesheet.json" ) ) );
  JsonTree animations{ loadAsset( "animations.json" ) };

  mEvents = EventManager::make();
  mEntities = EntityManager::make(mEvents);
  mSystemManager = SystemManager::make( mEntities, mEvents );
  mSystemManager->add<MovementSystem>();
  auto physics = mSystemManager->add<PhysicsSystem2d>();
  physics->createBoundaryRect( getWindowBounds() );
  auto renderer = mSystemManager->add<BatchRenderSystem2d>();
  renderer->setTexture( atlas->getTexture() );
  shared_ptr<SpriteAnimationSystem> sprite_system{ new SpriteAnimationSystem{ atlas, animations } };
  mSystemManager->add( sprite_system );
  mSystemManager->configure();

  Rand r;
  Vec2f center = getWindowCenter();
  Entity entity;
  for( int i = 0; i < 10000; ++i )
  {
    entity = mEntities->create();
    auto loc = shared_ptr<Locus>{ new Locus };
    // get an animation out of the sprite system
    auto anim = sprite_system->createSpriteAnimation( "dot" );
    loc->position = { r.nextFloat( getWindowWidth() ), r.nextFloat( getWindowHeight() ) };
    loc->rotation = r.nextFloat( M_PI * 2 );
    loc->registration_point = { 0, 0 };
    float dist = loc->position.distance( center );
    ColorA color{ CM_HSV, 0.0f, 0.0f, lmap( dist, 0.0f, 0.75f * getWindowWidth(), 0.0f, 1.0f ), 1.0f };
//    entity.assign( physics->createBox( loc->position, atlas->get( "d-0001" ).size / 12.0f, loc->rotation ) );
    auto mesh = entity.assign<RenderMesh2d>( 4, dist );
    for( auto &v : mesh->vertices )
    {
      v.color = color;
    }
    entity.assign( anim );
    entity.assign( loc );
  }

  getWindow()->getSignalMouseDown().connect( [=]( MouseEvent &event ) mutable
  {
    if( entity.valid() )
    {
      if( entity.component<SpriteAnimation>() )
      {
        cout << "Removing Sprite Animation component: " << entity << endl;
        entity.remove<SpriteAnimation>();
      }
      else
      {
        cout << "Adding Mesh component: " << entity << endl;
        auto mesh = RenderMesh2dRef{ new RenderMesh2d{ 4 } };
        // perhaps have a component to hang on to texturing data
        mesh->setAsTexture( atlas->get( "dl-0001" ) );
        mesh->render_layer = 1000;
        ColorA color{ 1.0f, 1.0f, 1.0f, 1.0f };
        for( auto &v : mesh->vertices )
        {
          v.color = color;
        }
        entity.assign<RenderMesh2d>( mesh );
      }
    }
  });

  mTimer.start();
}

void PupTentApp::update()
{
  double dt = mTimer.getSeconds();
  mTimer.start();
  Timer up;
  up.start();
  mSystemManager->system<PhysicsSystem2d>()->stepPhysics(); // could parallelize this with sprite animation and some other things...
  mSystemManager->update<PhysicsSystem2d>( dt );
  mSystemManager->update<MovementSystem>( dt );
  mSystemManager->update<SpriteAnimationSystem>( dt );
  mSystemManager->update<BatchRenderSystem2d>( dt );
  double ms = up.getSeconds() * 1000;
  mAverageUpdateTime = (mAverageUpdateTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Update: " << mAverageUpdateTime << ", " << ms << endl;
  }
}

void PupTentApp::draw()
{
	gl::clear( Color::black() );
  gl::disableDepthRead();
  gl::disableDepthWrite();
  gl::color( Color::white() );
  Timer dr;
  dr.start();
  mSystemManager->system<BatchRenderSystem2d>()->draw();
//  mSystemManager->system<PhysicsSystem2d>()->debugDraw();
  double ms = dr.getSeconds() * 1000;
  mAverageRenderTime = (mAverageRenderTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Render ms: " << mAverageRenderTime << ", " << ms << endl;
  }
}

CINDER_APP_NATIVE( PupTentApp, RendererGl( RendererGl::AA_MSAA_8 ) )

<|endoftext|>


<commit_before>/*

    IMPORTANT! This file is auto-generated each time you save your
    project - if you alter its contents, your changes may be overwritten!

*/

#include "AppConfig.h"
#include <juce_video/juce_video.cpp>
<commit_msg>Delete juce_video.cpp<commit_after><|endoftext|>