Форум программистов, компьютерный форум, киберфорум
Наши страницы

Пишу игровой движок на C++. 019. Подготовка к загрузке картинки

Войти
Регистрация
Восстановить пароль
Сайт движка - gost.imsoftworks.info
Исходные коды движка - https://github.com/532235/GoST
Документация
Примеры кода программ - https://github.com/532235/GoST/wiki

Другой хобби-проект в группе в вк https://vk.com/club154291467
Оценить эту запись

Пишу игровой движок на C++. 019. Подготовка к загрузке картинки

Запись от 532235 размещена 17.12.2017 в 04:07

Нужно загрузить картинку, создать текстуру и наложить её на квадрат.

Картинку будет грузить плагин для загрузки картинок, текстуру будет создавать плагин D3D11.

Первым поддерживаемым форматом будет BMP файл.

Вот некоторые форматы самого .bmp (форматы пикселя)
1bit ONE_BIT - точка либо чёрная либо белая
4bit X1R1G1B1 - предположение что это так
8bit X2R2G2B2 - предположение что это так
16bit A1R5G5B5
16bit X1R5G5B5
16bit A4R4G4B4
16bit X4R4G4B4
16bit R5G6B5
24bit R8G8B8
32bit X8R8G8B8
32bit A8R8G8B8

Все эти типы должны быть определены.
в gtImage.h уже заранее написал структуру. остаётся дополнить.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
enum format{
 
            FMT_ONE_BIT,
            
            FMT_X1R1G1B1,
            FMT_X2R2G2B2,
            
            FMT_A1R5G5B5,
            FMT_X1R5G5B5,
            
            FMT_A4R4G4B4,
            FMT_X4R4G4B4,
            
            FMT_R5G6B5,
            
            FMT_X8R8G8B8,
            FMT_A8R8G8B8,
 
            FMT_R8G8B8A8,
 
            FMT_R8G8B8,
 
 
            //  OpenGL
            FMT_COMPRESSED_RGBA_S3TC_DXT1 = 0x83F1,
            FMT_COMPRESSED_RGBA_S3TC_DXT3 = 0x83F2,
            FMT_COMPRESSED_RGBA_S3TC_DXT5 = 0x83F3
 
        }format;
-----------

Задача плагина, заполнить массив gtImage::data и настроить информацию о картинке.

Думаю, что, выделять и освобождать память в плагине не нужно.

Лучше будет так:
- объект gtImage создаётся внутри движка.
- при обращении к плагину в момент чтения файла, плагину передаётся указатель на этот объект.
- плагин проверяет картинку на корректность, если все хорошо, узнаёт, сколько нужно выделить памяти для gtImage::data
- плагин вызывает СПЕЦИАЛЬНУЮ функцию из движка, передавая ей указатель на объект gtImage, указывая размер в байтах сколько памяти нужно выделить.
- далее он заполняет массив gtImage::data

Всё выделение и освобождение памяти будет вестись в gost.dll
Надо реализовать соответствующую функцию.
gtMainSystem.h
C++
1
2
3
4
5
    //  Выделяет память размером size. Для освобождения нужно вызвать freeMemory
virtual bool    allocateMemory( void** data, u32 size ) = 0;
 
    //  Освобождает память, выделенную с помощью allocateMemory
virtual void    freeMemory( void** data ) = 0;
реализация в классе gtMainSystemCommon
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
    //  Выделяет память размером size. Для освобождения нужно вызвать freeMemory
bool gtMainSystemCommon::allocateMemory( void** data, u32 size ){
    GT_ASSERT1( !(*data), "Memory block is not free or pointer not set nullptr", "*data==nullptr" );
    *data = std::malloc( size );
    return (*data)?true:false;
}
 
    //  Освобождает память, выделенную с помощью allocateMemory
void gtMainSystemCommon::freeMemory( void** data ){
    GT_ASSERT1( *data, "Memory block is not allocated or set nullptr", "*data!=nullptr" );
    std::free( *data );
    *data = nullptr;
}
Чтобы было удобно пользоваться, добавил статичный метод
gtMainSystem::getInstance
C++
1
2
3
    //  возвратит указатель на gtMainSystem
    //  альтернатива this так как this не работает в статических методах
GT_API static gtMainSystem* getInstance( void );
Реализация в common классе
C++
1
2
3
gtMainSystem*   gtMainSystem::getInstance( void ){
    return gtMainSystemCommon::getInstance();
}
Небольшой тест в плагине D3D11
C++
1
2
3
4
5
6
7
8
void * data;
gtMainSystem::getInstance()->allocateMemory( &data, 3u );
s8 * s8data = (s8*)data;
s8data[ 0u ] = 'A';
s8data[ 1u ] = '1';
s8data[ 2u ] = 0;
MessageBoxA( 0, s8data, 0, 0 );
gtMainSystem::getInstance()->freeMemory( &data );

-------------------------------
Возврат к плагину.

Движок должен знать какие форматы поддерживает плагины.
При сканировании папок на поиск плагинов, когда попадается плагин импорта картинок, будет инициализироваться массив со строками хранящими расширение файла.
Будет 2 способа загрузки картинки.
1 - определяется расширение файла, потом идёт поиск в массиве того плагина, у которого указано это расширение, потом идёт проба загрузить картинку, если не удача, то, вполне может быть что в папке есть ещё один загрузчик такого формата, и, если это так то будет ещё попытка для загрузки.
2 - загружается, указав GUID, как в render плагине.

Стандартные плагины будут иметь guid, которые указаны в gtPluginSystem.h
Добаляю туда
C++
1
2
//  указывается при точном выборе плагина загрузки картинок
const gtString GT_GUID_IMPORT_IMAGE_BMP( u"{B0904D7B-5AA3-4023-BC99-ECA2232E1EBE}" );
плагин gtBMP пока выглядит так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifdef _DEBUG
#pragma comment(lib, "gost_d.lib")
#else 
#pragma comment(lib, "gost.lib")
#endif
 
extern "C"{
    __declspec(dllexport) void  GetPluginInfo( gtPluginInfo& info ){
        info.m_author.assign( u"532235" );
        info.m_description.assign( u"Import .bmp .dib .rle files" );
        info.m_GUID.assign( GT_GUID_IMPORT_IMAGE_BMP );
        info.m_name.assign( u"Bitmap file importer" );
        info.m_type = gtPluginType::import_image;
    }
}
Теперь нужно придумать как получить поддерживаемые расширения файлов.
ранее делал строку с аргументами, которая хранилась в GetPluginInfo

На сей раз пусть будут 2 функции, 1 для получения количества расширений, другая на получение самих расширений.
Так проще.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__declspec(dllexport) u32   PluginGetExtCount( void ){
    return 3u;
}
 
__declspec(dllexport) s8*   PluginGetExtension( u32 id ){
    GT_ASSERT1( id < 3u; "Bad argument", "id < 3u" );
 
    s8 * exts[ 3u ] = {
        "bmp",
        "dib",
        "rle"
    };
 
    return exts[ id ];
}
Как видно, расширения указаны в нижнем регистре.
При проверке расширений, будет использоваться сравнение строк, а это сравнение чувствительно к регистру.
По этому нужно добавить функции делающие строки полностью в высоком либо в низком регистре.

В gtUtilities.h добаляю
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template<typename Type>
GT_FORCE_INLINE void stringToLower( Type& str ){
            
    u32 sz = str.size();
 
    for( u32 i = 0u; i < sz; ++i ){
        auto c = str[ i ];
        if( c <= 'Z' && c >= 'A' )
            str[ i ] += 32;
    }
 
}
 
template<typename Type>
GT_FORCE_INLINE void stringToUpper( Type& str ){
            
    u32 sz = str.size();
 
    for( u32 i = 0u; i < sz; ++i ){
        auto c = str[ i ];
        if( c >= 'a' && c <= 'z' )
            str[ i ] -= 32;
    }
 
}
Так же нужно создать указатели на эти функции.
gtPluginSystem.h
C++
1
2
3
using gtPluginGetExtCount_t = u32(*)( void );
using gtPluginGetExtension_t = s8*(*)( u32 id );
using gtPluginLoadImage_t = bool(*)(gtImage*,gtString*);
-------------------------------
Картинку должен загружать gtMainSystem, и конечно же удалять её.
C++
1
2
3
4
5
6
7
8
    //  Загрузит gtImage, если расширение поддерживается хоть каким-то плагином
virtual gtImage*    loadImage( const gtString& fileName ) = 0;
 
    //  Загрузит gtImage плагином имеющим указанный код
virtual gtImage*    loadImage( const gtString& fileName, const gtString& pluginGUID ) = 0;
 
    //  Удаляет картинку из памяти
virtual void        removeImage( gtImage* ) = 0;
-------------------------------
Для удобства, каждый тип плагина должен быть описан в классе(ибо функция сканирования папки разрастается).
Ранее уже сделал для render плагина, но класс находится в файле gtPluginSystemImpl
Создаю .h и .cpp файлы для gtPluginRender, и переношу всё туда.
Реализация всех методов в .cpp файле, так же добавил
C++
1
2
3
const gtPluginInfoDL&   getInfo( void );
    //  проверит есть ли нужные функции в плагине
bool checkLibraryFunctions( void );
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const gtPluginInfoDL&   gtPluginRender::getInfo( void ){
    return m_info;
}
    //  проверит есть ли нужные функции в плагине
bool gtPluginRender::checkLibraryFunctions( GT_LIBRARY_HANDLE lib ){
    gtLoadGPUDriver_t gtLoadGPUDriver =     (gtLoadGPUDriver_t)GT_LOAD_FUNCTION(lib,"gtLoadGPUDriver");
    if( !gtLoadGPUDriver ){
        gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"gtLoadGPUDriver", m_info.m_path.data() );
        GT_FREE_LIBRARY( lib );
        return false;
    }
 
    return true;
}
Нужно сделать класс подобный gtPluginRender
Класс будет очень похожим, по этому, возможно сделать общий интерфейс.

gtPlugin.h
Убрал в него некоторые структуры из gtPluginSystem
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#pragma once
#ifndef __GT_PLUGIN_H__
#define __GT_PLUGIN_H__
 
 
/*
*/
 
namespace gost{
 
        //  тип плагина
    enum class gtPluginType{
 
        //  плагины должны быть правильно инициализированы
        unknown,
 
        //  рендер
        render,
 
        //  импортёр картинок
        import_image,
 
        //  импортёр моделей
        import_model
 
        // для начала хватит
    };
 
        //  общая информация о плагине
    struct gtPluginInfo{
        gtPluginInfo( void ):
            m_type( gtPluginType::unknown )
        {
                //  нельзя выделять память в одном модуле и освобождать в другом
                //  выход за пределы - на совести разработчика плагина
            m_name.reserve( 64u );
            m_author.reserve( 64u );
            m_url.reserve( 64u );
            m_email.reserve( 64u );
            m_company.reserve( 64u );
            m_description.reserve( 512u );
            m_GUID.reserve( 64u );
        }
 
        //  тип плагина
        gtPluginType m_type;
 
        //  название плагина
        gtString m_name;
 
        //  автор
        gtString m_author;
 
        //  ссылка на сайт
        gtString m_url;
 
        //  контактный имейл
        gtString m_email;
 
        //  имя компании если юр лицо
        gtString m_company;
 
        //  описание
        gtString m_description;
 
        //  уникальный ID. по сути любая строка.
        //  имя по аналогии с GUID. {41B20362-9FC0-4C40-9903-B8D2FF98CF88}
        gtString m_GUID;
 
    };
 
    /*  Информация о плагине(более близкая к самому модулю).
        Содержит путь к файлу
        хэндл,
        так же общая информация gtPluginInfo*/
    struct gtPluginInfoDL{
 
        gtPluginInfoDL( void ):
            m_handle( nullptr )
        {}
 
        ~gtPluginInfoDL( void ){}
 
        //  путь к файлу
        gtString m_path;
        
        //  handle плагина
#ifdef GT_EXPORTS
        GT_LIBRARY_HANDLE
#else
        void*
#endif
            m_handle;
 
        //  общая информация
        gtPluginInfo m_info;
    };
    
    class gtPlugin : public gtRefObject{
 
    protected:
 
        //  информация
        gtPluginInfoDL  m_info;
        
            //  загружен ли плагин
        bool m_isLoad;
 
    public:
 
        gtPlugin( void ):
            m_isLoad( false )
        {}
 
        virtual ~gtPlugin( void ){  }
 
        bool isLoad( void ) const { return m_isLoad; }
 
            //  загрузить плагин
        virtual void load( void ) = 0;
 
            //  выгрузитьплагин
        virtual void unload( void ) = 0;
 
        virtual const gtPluginInfoDL&   getInfo( void ) = 0;
 
            //  проверит есть ли нужные функции в плагине
        virtual bool checkLibraryFunctions( 
#ifdef GT_EXPORTS
            GT_LIBRARY_HANDLE
#else
        void*
#endif
        ) = 0;
 
 
 
    };
 
}
 
#endif
Шаманя над реализацией загрузки выгрузки rener плагина, я сделал изменения, улучшения.
Убрал gtList который хранил указатели только на загруженные плагины.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class gtPluginRender;
class gtPluginSystemImpl GT_FINAL : public gtPluginSystem{
 
        void scanFolder( const gtString& );
 
        u32 m_numOfPlugins;
 
        //  доступные для загрузки
        gtArray<gtPtr<gtPluginRender>> m_renderPluginCache;
        
    public:
        gtPluginSystemImpl( void );
        virtual ~gtPluginSystemImpl( void );
 
        bool init( void );
 
            //  получить количество плагинов в папке plugins
        u32 getNumOfPlugins( void );
 
            //  загружает видео плагин
        gtDriver*   loadRenderPlugin( const gtDriverInfo& params );
 
            //  выгружает и удаляет из коллекции
        void        unloadRenderPlugin( gtDriver* );
 
    };
в функции сканирования папки теперь
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if( pi.m_type == gtPluginType::unknown ){
                    gtLogWriter::printWarning( u"Unsupported plugin [%s]", o->path );
                }else{
                    gtLogWriter::printInfo( u"Add plugin: %s", pi.m_name.data() );
                    gtLogWriter::printInfo( u"Description: %s", pi.m_description.data() );
                }
                
                if( pi.m_type == gtPluginType::render ){
                    
                    gtPtr<gtPluginRender> plugin = gtPtrNew<gtPluginRender>( new gtPluginRender( &pi_dl ) );
 
                    if( !plugin->checkLibraryFunctions( lib ) )
                        continue;
                                        
                    m_numOfPlugins++;
 
                    this->m_renderPluginCache.push_back( plugin.data() );
 
                }
Создание gtDriver и уничтожение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
gtDriver*   gtPluginSystemImpl::loadRenderPlugin( const gtDriverInfo& params ){
    
    u32 sz = m_renderPluginCache.size();
 
    if( !sz ){
        gtLogWriter::printError( u"Can not load render plugin [%s]. No plugin.", params.m_GUID.data() );
        return nullptr;
    }
 
    for( u32 i = 0u; i < sz; ++i ){
        auto * o = &m_renderPluginCache[ i ];
        if( o->data()->getInfo().m_info.m_GUID == params.m_GUID ){
            
            o->data()->loadDriver( params );
            
            return o->data()->m_driver[ o->data()->m_driver.size() - 1u ].driver;
        }
    }
    
    
    return nullptr;
}
 
void gtPluginSystemImpl::unloadRenderPlugin( gtDriver* d ){
    u32 sz = m_renderPluginCache.size();
 
    for( u32 i = 0u; i < sz; ++i ){
        auto * o = &m_renderPluginCache[ i ];
 
        for( u32 j = 0u; j < o->data()->m_driver.size(); ++j ){
            if( o->data()->m_driver[ j ].driver == d ){
                o->data()->unloadDriver( j );
                break;
            }
        }
    }
}
Теперь конкретно gtPluginRender. Нужно его подправить, сделать потомком от gtPlugin, потом уже перейти на плагин загрузки картинки.
Класс gtPluginRender находится внутри движка, в своих .h и .cpp файлах
вот так выгядит теперь gtPluginRender.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#pragma once
#ifndef __GT_PLUGIN_RENDER_H__
#define __GT_PLUGIN_RENDER_H__
 
 
namespace gost{
 
    /*
        Это обёртка к render плагину.
        Хранит информацию.
        Благодоря этому можно грузить и выгружать плагин 
        используя методы load unload
    */
    class gtPluginRender : public gtPlugin{
    public:
 
        gtPluginRender( gtPluginInfoDL* info );
 
        ~gtPluginRender( void );
        
        struct Driver{
 
            Driver( void (*f)(), gtDriver* d ):
                loadPlugin( f ),
                driver( d )
            {}
 
            //  указатель на функцию
            //  render плагин - указывает на функцию запуска.
            void (*loadPlugin)();
 
                //  видео драйвер данного плагина
            gtDriver* driver;
 
        };
 
        gtArray<Driver> m_driver;
 
            //  загрузить плагин
        void loadDriver( const gtDriverInfo& params );
 
            //  выгрузить драйвер под номером id
        void unloadDriver( u32 id );
 
            //  загрузить плагин
        void load( void );
 
            //  выгрузитьплагин
        void unload( void );
 
        const gtPluginInfoDL&   getInfo( void );
 
            //  проверит есть ли нужные функции в плагине
        bool checkLibraryFunctions( GT_LIBRARY_HANDLE );
    };
 
}
 
 
#endif
gtPluginRender грузит 1 плагин.
Для того чтобы создать несколько gtDriver из одного плагина (фиг знает, может это пригодится), добавил структуру Driver, который хранит указатель на gtDriver и функцию инициализации.
методы load и unload нужны для таких плагинов как импорт/экспорт ресурсов, по этому они будут пустые.
реализация
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
gtPluginRender::gtPluginRender( gtPluginInfoDL* info )
{
    m_info = *info;
}
 
gtPluginRender::~gtPluginRender( void ){
    u32 sz = m_driver.size();
    for( u32 i = sz-1u; i >= 0u; --i  ){
        unloadDriver( i );
        if( !i ) break;
    }
}
 
 
void gtPluginRender::loadDriver( const gtDriverInfo& params ){
        
        if( !m_info.m_handle )
            m_info.m_handle =   GT_LOAD_LIBRARY( (wchar_t*)m_info.m_path.data() );
 
        if( !m_info.m_handle ){
            gtLogWriter::printWarning( u"Can not load plugin [%s]", m_info.m_path.data() );
            return;
        }
 
        gtLoadGPUDriver_t loadProc = (gtLoadGPUDriver_t)GT_LOAD_FUNCTION( m_info.m_handle, "gtLoadGPUDriver" );
        if( !loadProc ){
            gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"gtLoadGPUDriver", m_info.m_path.data() );
            GT_FREE_LIBRARY( m_info.m_handle );
            return;
        }
                
 
        m_driver.push_back(
            gtPluginRender::Driver( 
                (void(*)())loadProc,
                ((gtLoadGPUDriver_t)loadProc)( gtMainSystemCommon::getInstance(), params )
             ));
 
        if( m_driver[ m_driver.size() - 1u ].driver ){
        //  setHandle( m_driver.data(), m_info.m_handle );
            m_isLoad = true;
 
        }else{
            if( !m_driver.size() )
                GT_FREE_LIBRARY( m_info.m_handle );
        }
}
 
void gtPluginRender::unloadDriver( u32 id ){
 
    GT_ASSERT2( (id < m_driver.size()), "id < m_driver.size()" );
 
    if( m_isLoad ){
 
        if( m_driver[ id ].driver ){
            m_driver[ id ].driver->release();
            m_driver[ id ].driver = nullptr;
            m_driver.erase( m_driver.begin() + id );
        }
 
        if( !m_driver.size() ){
            GT_FREE_LIBRARY( m_info.m_handle );
            m_info.m_handle = nullptr;
 
            m_isLoad = false;
        }
    }
}
 
 
const gtPluginInfoDL&   gtPluginRender::getInfo( void ){
    return m_info;
}
 
    //  проверит есть ли нужные функции в плагине
bool gtPluginRender::checkLibraryFunctions( GT_LIBRARY_HANDLE lib ){
    gtLoadGPUDriver_t gtLoadGPUDriver =     (gtLoadGPUDriver_t)GT_LOAD_FUNCTION(lib,"gtLoadGPUDriver");
    if( !gtLoadGPUDriver ){
        gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"gtLoadGPUDriver", m_info.m_path.data() );
        GT_FREE_LIBRARY( lib );
        return false;
    }
 
    return true;
}
 
    //  загрузить плагин
void gtPluginRender::load( void ){
}
 
    //  выгрузитьплагин
void gtPluginRender::unload( void ){
}

-----------------------------------------------
Возврат к BMP плагину
В gtPluginSystemImpl в фукнции сканирования папки нужно обработать этот тип плагина.
C++
1
2
3
4
5
6
7
8
9
10
11
else if( pi.m_type == gtPluginType::import_image ){
 
                    gtPtr<gtPluginImportImage> plugin = gtPtrNew<gtPluginImportImage>( new gtPluginImportImage( &pi_dl ) );
 
                    if( !plugin->checkLibraryFunctions(lib))
                        continue;
 
                    m_numOfPlugins++;
 
                    this->m_importImagePluginCache.push_back( plugin.data() );
                }
как и в случае с render плагином добавил массив в котором будут хранится все доступные плагины
C++
1
gtArray<gtPtr<gtPluginImportImage>> m_importImagePluginCache;
Обёртка к плагину
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#pragma once
#ifndef __GT_PLUGIN_IMPORT_IMAGE_H__
#define __GT_PLUGIN_IMPORT_IMAGE_H__
 
namespace gost{
 
    /*
    */
    class gtPluginImportImage : public gtPlugin{
        gtPluginLoadImage_t f_loadImage;
    public:
 
        gtPluginImportImage( gtPluginInfoDL* info );
 
        ~gtPluginImportImage( void );
        
            //  загрузить плагин
        void load( void );
 
            //  выгрузитьплагин
        void unload( void );
 
        const gtPluginInfoDL&   getInfo( void );
 
            //  проверит есть ли нужные функции в плагине
        bool checkLibraryFunctions( GT_LIBRARY_HANDLE );
 
        gtArray<gtString> m_extensions;
 
        void loadImage( gtString*, gtImage** );
    };
 
}
 
 
#endif
Но это ещё не всё, в сканировании. Нужно получить расширение файлов, сохранить их.
добавил
C++
1
gtArray<gtString> m_extensions;
Получаю расширения в gtPluginImportImage::checkLibraryFunctions
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
    u32 sz = gtPluginGetExtCount();
    if( sz ){
        for( u32 i = 0u; i < sz; ++i ){
            s8 * str = gtPluginGetExtension( i );
            gtString ext;
            util::stringAppend( ext, str );
            util::stringToLower( ext );
            m_extensions.push_back( ext );
        }
        return true;
    }
    return false;
}
Чтобы в std::stringw правильно прибавить массив char * сделал шаблонную функцию.
Можно к string прибавить string с char32_t
gtUtilities.h
C++
1
2
3
4
5
6
7
8
9
//  добаляет к str строку иного типа
        template<typename Type, typename AnotherType>
        GT_FORCE_INLINE void stringAppend( Type& str, AnotherType& other ){
            u32 sz = 0u;
            auto * p = &other[0];
            while( *p++ ) sz++;
            for( u32 i = 0u; i < sz; ++i )
                str += other[ i ];
        }
--------------------------------------
Наконец реализация
C++
1
2
3
virtual gtImage*    loadImage( const gtString& fileName ) = 0;
virtual gtImage*    loadImage( const gtString& fileName, const gtString& pluginGUID ) = 0;
virtual void        removeImage( gtImage* ) = 0;
Реализация в gtMainSystemCommon
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    //  Загрузит gtImage, если расширение поддерживается хоть каким-то плагином
gtImage*    gtMainSystemCommon::loadImage( const gtString& fileName ){
    gtPtr<gtImage> image = gtPtrNew<gtImage>( this->m_pluginSystem->importImage( fileName ) );
    if( !image.data() ) return nullptr;
    image->addRef();
    return image.data();
}
 
    //  Загрузит gtImage плагином имеющим указанный код
gtImage*    gtMainSystemCommon::loadImage( const gtString& fileName, const gtString& pluginGUID ){
    gtPtr<gtImage> image = gtPtrNew<gtImage>( this->m_pluginSystem->importImage( fileName, pluginGUID, true ) );
    if( !image.data() ) return nullptr;
    image->addRef();
    return image.data();
}
 
    //  Удаляет картинку из памяти
void        gtMainSystemCommon::removeImage( gtImage* image ){
    if( image ){
        image->release();
        image = nullptr;
    }
}
MainSystem через PluginSystem загружает картинку.

в gtPluginSystemImpl для этого добавлено
C++
1
2
    //  загружает картинку
gtImage *   importImage( const gtString& fileName, const gtString& guid = gtString(), bool useguid = false );
реализация
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    //  загружает картинку
gtImage * gtPluginSystemImpl::importImage( const gtString& fileName, const gtString& guid, bool useguid){
 
    if( !gtFileSystem::existFile( fileName ) ){
        gtLogWriter::printWarning( u"Can not load image [%s]. File not exist.", fileName.data() );
        return nullptr;
    }
 
    gtString file = fileName;
    util::stringFlipSlash( file );
    
    gtString ext;
    util::stringGetExtension( ext );
    util::stringToLower( ext );
    
    gtImage * image = new gtImage;
 
    u32 sz = this->m_importImagePluginCache.size();
    for( u32 i = 0u; i < sz; ++i ){
        auto * o = &this->m_importImagePluginCache[ i ];
 
        if( useguid ){
            if( o->data()->getInfo().m_info.m_GUID == guid ){
                o->data()->load();
                o->data()->loadImage( &file, &image );
                break;
            }
        }else{
            u32 esz = o->data()->m_extensions.size();
            for( u32 j = 0u; j < esz; ++j ){
                if( o->data()->m_extensions[ j ] == ext ){
                    o->data()->load();
                    o->data()->loadImage( &file, &image );
                    if( image->data ) break;
                }
            }
        }
 
    }
 
    if( image->data ){
        gtLogWriter::printInfo(u"Loading image: %s", fileName.data());
        return image;
    }
 
    delete image;
    return nullptr;
}
реализация обёртки
gtPluginImportImage.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
gtPluginImportImage::gtPluginImportImage( gtPluginInfoDL* info ){
    m_info = *info;
}
 
gtPluginImportImage::~gtPluginImportImage( void ){
    unload();
}
        
    //  загрузить плагин
void gtPluginImportImage::load( void ){
    if( !m_isLoad ){
 
        m_info.m_handle = GT_LOAD_LIBRARY((wchar_t*)m_info.m_path.data());
 
        if( !m_info.m_handle ){
            gtLogWriter::printWarning( u"Can not load plugin [%s]", m_info.m_path.data() );
            return;
        }
 
        gtPluginLoadImage_t loadProc = (gtPluginLoadImage_t)GT_LOAD_FUNCTION( m_info.m_handle, "PluginLoadImage" );
        if( !loadProc ){
            gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"PluginLoadImage", m_info.m_path.data() );
            GT_FREE_LIBRARY( m_info.m_handle );
            return;
        }
 
        f_loadImage = loadProc;
 
        m_isLoad = true;
    }
}
 
    //  выгрузить плагин
void gtPluginImportImage::unload( void ){
    if( m_isLoad ){
 
        if( m_info.m_handle )
            GT_FREE_LIBRARY( m_info.m_handle );
 
        m_isLoad = false;
    }
}
 
const gtPluginInfoDL&   gtPluginImportImage::getInfo( void ){
    return m_info;
}
 
    //  проверит есть ли нужные функции в плагине
bool gtPluginImportImage::checkLibraryFunctions( GT_LIBRARY_HANDLE lib ){
 
    gtPluginGetExtCount_t gtPluginGetExtCount = (gtPluginGetExtCount_t)GT_LOAD_FUNCTION(lib,"PluginGetExtCount");
    if( !gtPluginGetExtCount ){
        gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"PluginGetExtCount", m_info.m_path.data() );
        GT_FREE_LIBRARY( lib );
        return false;
    }
 
    gtPluginGetExtension_t gtPluginGetExtension = (gtPluginGetExtension_t)GT_LOAD_FUNCTION(lib,"PluginGetExtension");
    if( !gtPluginGetExtension ){
        gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"PluginGetExtension", m_info.m_path.data() );
        GT_FREE_LIBRARY( lib );
        return false;
    }
 
    gtPluginLoadImage_t gtPluginLoadImage = (gtPluginLoadImage_t)GT_LOAD_FUNCTION(lib,"PluginLoadImage");
    if( !gtPluginLoadImage ){
        gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"PluginLoadImage", m_info.m_path.data() );
        GT_FREE_LIBRARY( lib );
        return false;
    }
 
    u32 sz = gtPluginGetExtCount();
    if( sz ){
        for( u32 i = 0u; i < sz; ++i ){
            s8 * str = gtPluginGetExtension( i );
            gtString ext;
            util::stringAppend( ext, str );
            util::stringToLower( ext );
            m_extensions.push_back( ext );
        }
        return true;
    }
    return false;
}
 
void gtPluginImportImage::loadImage( gtString* fileName, gtImage** pImage ){
    GT_ASSERT2( m_isLoad, "m_isLoad==true, plugin is not load" );
    this->f_loadImage( *pImage, fileName );
}
Размещено в Игровой движок
Просмотров 231 Комментарии 0
Всего комментариев 0

Комментарии

 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru