Delta time

    Delta time is a time for one iteration of main loop.

    Add `float m_deltaTime = 0.f;` in slFrameworkImpl

    Add `static float* GetDeltaTime();` in slFramework and return pointer.

    Calculate delta time in `void slFramework::Update()`

    static clock_t then = 0;
    clock_t now = clock();
    g_framework->m_deltaTime = (float)(now - then) / CLOCKS_PER_SEC;
    then = now;
    

    Log

    Framework should be able to write some information, warnings, errors.

    class slLog
    {
    public:
    	static void Print(const char* s, ...);
    	static void Print(const wchar_t* s, ...);
    
    	static void PrintInfo(const char* s, ...);
    	static void PrintInfo(const wchar_t* s, ...);
    
    	static void PrintWarning(const char* s, ...);
    	static void PrintWarning(const wchar_t* s, ...);
    
    	static void PrintError(const char* s, ...);
    	static void PrintError(const wchar_t* s, ...);
    
    	static void SetCallbackA(void(*)(const char*));
    	static void SetCallbackW(void(*)(const wchar_t*));
    };
    

    In implementation I use other class.

    static slLogImpl g_log;
    
    void slLog::Print(const char* s, ...)
    {
    	va_list vl;
    	va_start(vl, s);
    	g_log.vprintf(s, vl);
    	va_end(vl);
    }
    void slLog::PrintInfo(const char* s, ...)
    {
    	Print("%s", "Info: ");
    
    	va_list vl;
    	va_start(vl, s);
    	g_log.vprintf(s, vl);
    	va_end(vl);
    }
    

    Class.

    class slLogImpl
    {
    public:
    	slLogImpl() 
    	{
    		m_cba = slLogDefaultCallbackA;
    		m_cbw = slLogDefaultCallbackW;
    	}
    
    	void vprintf(const char* s, va_list vl);
    	void vwprintf(const wchar_t* s, va_list vl);
    
    	void(*m_cba)(const char*);
    	void(*m_cbw)(const wchar_t*);
    };
    void slLogImpl::vprintf(const char* s, va_list vl)
    {
    	char buffer[1002];
    	vsnprintf_s(buffer, 1002, s, vl);
    	m_cba(buffer);
    }
    void slLogImpl::vwprintf(const wchar_t* s, va_list vl)
    {
    	wchar_t buffer[1002];
    	vswprintf_s(buffer, 1002, s, vl);
    	m_cbw(buffer);
    }
    

    Default print functions

    void slLogDefaultCallbackA(const char* s)
    {
    	printf(s);
    }
    
    void slLogDefaultCallbackW(const wchar_t* s)
    {
    	wprintf(s);
    }
    

    Also I changed code in assert and stacktracer. Now they use slLog.

    Math

    Another static class.

    It will have even functions like `cross` or `dot` for vectors, so I don't need to add them in vector classes.

    In this class I will add all other functions, like for matrices and other things.

    Another thing is I use precomputed values for some functions:

    // Expect value form -1 to +1
    static float acos(float);
    
    // Expect value form -1 to +1
    static float asin(float);
    
    // Expect value form -2 to +2
    static float atan(float);
    
    // Expect value form -1 to +1
    static float atan2(float y, float x);
    
    // Expect value from -PI to +PI
    static float cos(float);
    static float sin(float);
    static float tan(float);
    

    And there is double versions too.

    Implemetation for `cos`

    float slMath::cos(float v)
    {
    	if (v < -3.141f) v = -3.141f;
    	if (v < 0.f) v = slMath::abs(v);
    	if (v > 3.141f) v = 3.141f;
    
    	uint32_t ind = (uint32_t)roundf(v * 1000.0f);
    
    	if(ind < 3143)
    		return g_cosf[ind];
    	return 0;
    }
    

    User must provide right values.

    g_cosf is an array

    static float g_cosf[] = {
    #include "cosf.inl"
    };
    

    cosf.inl is a file with numbers.

    Vector

    4 versions. 2 xyz, 2 xyzw. float and double

    I will use only like `operator+`. All functions must be in slMath.

    class slVec3
    {
    public:
    	slVec3();
    	slVec3(double x, double y, double z);
    	slVec3(float v);
    	slVec3(double v);
    	slVec3(int32_t v);
    	slVec3(const slVec3&);
    	slVec3(const slVec3f&);
    	slVec3(const slVec4&);
    	slVec3(const slVec4f&);
    	double operator[](uint32_t index) const;
    	double& operator[](uint32_t index);
    	slVec3 operator+(const slVec3& v)const;
    	slVec3 operator+(const slVec3f& v)const;
    	slVec3 operator+(const slVec4& v)const;
    	slVec3 operator+(const slVec4f& v)const;
    	slVec3 operator-(const slVec3& v)const;
    	slVec3 operator-(const slVec3f& v)const;
    	slVec3 operator-(const slVec4& v)const;
    	slVec3 operator-(const slVec4f& v)const;
    	slVec3 operator*(const slVec3& v)const;
    	slVec3 operator*(const slVec3f& v)const;
    	slVec3 operator*(const slVec4& v)const;
    	slVec3 operator*(const slVec4f& v)const;
    	slVec3 operator/(const slVec3& v)const;
    	slVec3 operator/(const slVec3f& v)const;
    	slVec3 operator/(const slVec4& v)const;
    	slVec3 operator/(const slVec4f& v)const;
    	slVec3 operator-()const;
    	slVec3& operator=(const slVec3& v);
    	slVec3& operator=(const slVec3f& v);
    	slVec3& operator=(const slVec4& v);
    	slVec3& operator=(const slVec4f& v);
    	bool operator==(const slVec3& v)const;
    	bool operator!=(const slVec3& v)const;
    
    	double x = 0.0;
    	double y = 0.0;
    	double z = 0.0;
    	double* data() { return &x; }
    };
    

    For example `cross` method (in slMath)

    void slMath::cross(const slVec3& v1, const slVec3& v2, slVec3& r)
    {
    	r.x = (v1.y * v2.z) - (v1.z * v2.y);
    	r.y = (v1.z * v2.x) - (v1.x * v2.z);
    	r.z = (v1.x * v2.y) - (v1.y * v2.x);
    }
    

    Other things

    In window I added

    void ToFullscreenMode();
    void ToWindowMode();
    

    New data for this

    slPoint m_currentSize;
    slPoint m_creationSize;
    slPoint m_sizePreFullscreen;
    bool m_isFullscreen = false;
    .....
    //slWindowWin32
    LONG m_stylePreFullscreen = 0;
    WINDOWPLACEMENT m_wndPlcmnt;
    

    Implementation

    void slWindow::ToFullscreenMode()
    {
        SL_ASSERT_ST(m_data.m_implementation);
        if (m_data.m_isFullscreen)
            return;
    
    #ifdef SL_PLATFORM_WINDOWS
        slWindowWin32* w32 = (slWindowWin32*)m_data.m_implementation;
        w32->m_stylePreFullscreen = GetWindowLong(w32->m_hWnd, GWL_STYLE);
        MONITORINFO mi = { sizeof(mi) };
        
        if (GetWindowPlacement(w32->m_hWnd, &w32->m_wndPlcmnt) &&
            GetMonitorInfo(MonitorFromWindow(w32->m_hWnd, MONITOR_DEFAULTTOPRIMARY), &mi))
        {
            m_data.m_sizePreFullscreen = m_data.m_currentSize;
    
            m_data.m_currentSize.x = mi.rcMonitor.right - mi.rcMonitor.left;
            m_data.m_currentSize.y = mi.rcMonitor.bottom - mi.rcMonitor.top;
         //   _set_current_rect();
    
            SetWindowLong(w32->m_hWnd, GWL_STYLE, WS_POPUP);
            SetWindowPos(w32->m_hWnd, HWND_TOP,
                mi.rcMonitor.left, mi.rcMonitor.top,
                mi.rcMonitor.right - mi.rcMonitor.left,
                mi.rcMonitor.bottom - mi.rcMonitor.top,
                SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
            m_data.m_isFullscreen = true;
            ShowWindow(w32->m_hWnd, SW_NORMAL);
        }
    #endif
    }
    
    void slWindow::ToWindowMode()
    {
        SL_ASSERT_ST(m_data.m_implementation);
        if (!m_data.m_isFullscreen)
            return;
    #ifdef SL_PLATFORM_WINDOWS
        slWindowWin32* w32 = (slWindowWin32*)m_data.m_implementation;
        SetWindowLong(w32->m_hWnd, GWL_STYLE, w32->m_stylePreFullscreen);
        
        m_data.m_currentSize = m_data.m_sizePreFullscreen;
    
      //  _set_current_rect();
    
        SetWindowPlacement(w32->m_hWnd, &w32->m_wndPlcmnt);
        SetWindowPos(w32->m_hWnd, NULL, 0, 0, 0, 0,
            SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
            SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
        m_data.m_isFullscreen = false;
        ShowWindow(w32->m_hWnd, SW_NORMAL);
    #endif
    }
    
    Download code