LINUX.ORG.RU

Мой проект e2dit, помогите советом

 ,


1

2

Всем привет, недавно выкладывал скриншот: Мой редактор уровней, в разработке
выложил исходный код: https://github.com/sysint64/e2dit.git

Очевидно что и код, и структура мягко говоря не очень, решил переоформить все, сделать сборку через cmake итд. И так как хочется все красиво сделать, хотелось бы совета у сообщества.
Сейчас начал новую структуру накидывать и получилось как-то так:

src/
   core/{*.h,*.cpp}
   math/{*.h,*.cpp}
   renderer/{*.h,*.cpp}
   system/{*.h,*.cpp}
   ui/{*.h,*.cpp}
res/
   ui/
   strings/

Пока так, там будет расширяться, ну и в данный момент у меня в основном файле у меня просто ужас:
#define GLEW_STATIC
#define GLM_FORCE_RADIANS
#define GLM_SWIZZLE
//#define GLM_FORCE_AVX for x86_64
#define GLM_FORCE_INLINE
#define GLM_FORCE_PURE

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <glm/gtx/fast_square_root.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/vector_angle.hpp>
//

#include "GL/glew.h"
//#include "GL/wglew.h"

#ifdef _win_
	#include "windows.h"
#endif
//
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <math.h>
#include <stdexcept>
#include <clocale>
#include <locale>
#include <iconv.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

#ifdef _linux_
	#include <mntent.h>
#endif

#include <unistd.h>
//
using namespace std;
//
void Terminate (const int type);
//
#include "Engine/Logger.h"

#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
//#include <SFML/Window/Mouse.hpp>

#include <iostream>
#include <pthread.h>

#include <SOIL/SOIL.h>
#include <FTGL/ftgl.h>

Решил начать с этого, как лучше все это по папкам распихать, думал все инклуды с glm перенести в math/main.h но может не лучшее решение. Так же думал все инклуды из std вынести в какойнить файл, например в system/main.h. Хотелось бы услышать ваши идеи и предпочтения.

★★★

думал все инклуды с glm перенести в math/main.h но может не лучшее решение. Так же думал все инклуды из std вынести в какойнить файл, например в system/main.h

Зачем, в каждый .cpp инклюдь только то, что в нем требуется использовать и не заморачивайся

kravich ★★★★
()
Последнее исправление: kravich (всего исправлений: 1)
Ответ на: комментарий от kravich

А вот у меня еще есть файл config.h, примерно такого содержания:

static int	WindowWidth  = 1400;
static int	WindowHeight = 840;
static int	ScreenWidth;
static int	ScreenHeight;
static int	OGLMajor = 3;
static int	OGLMinor = 3;
static int	AntiAliasing = 16;
static int	MouseX, MouseY;
static int	Shift;
static float	CurrTime, DeltaTime, LastTime;
static float	FPS;
static string	CurrentTheme = "Hexagon";
static string	lang = "eng";
static bool	DialogOpened;
static bool	HideCursor = false;
static string	ExeDir;
const float	pi = 3.14159265358979323846264338327950f;

Может большинство этих параметров, например pi, OGLMajor, OGLMinor вынести куданить в m4 препроцессором, и не создавать вообще config.h?

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64
#define GLM_FORCE_RADIANS
#define GLM_SWIZZLE
//#define GLM_FORCE_AVX for x86_64
#define GLM_FORCE_INLINE
#define GLM_FORCE_PURE

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <glm/gtx/fast_square_root.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/vector_angle.hpp>

И вот такую пачку дефйнов приходится писать каждый раз, когда инклудишь glm/glm.h? Да, тогда все это стоит вынести в один хедер.

kravich ★★★★
()
Последнее исправление: kravich (всего исправлений: 1)
Ответ на: комментарий от Int64

Не, m4 точно не стоит, усложнение процесса сборки и вообще лишняя зависимость. Лично я эти параметры оставил бы в config.h, только сделал бы их именованными константами. И вообще отделил бы глобальные параметры от их начальных значений (начальные значения берутся из .ini-конфига, если конфиг отсутствует, создается дефолтный)

kravich ★★★★
()
Последнее исправление: kravich (всего исправлений: 1)
Ответ на: комментарий от Int64

файл config.h

А меняешь когда-нибудь эти параметры? Ведь static переменные доступны только внутри одной единицы трансляции. Компилятор не ругается про неиспользуемые глобальные static переменные?

3.14159265358979323846264338327950f

Мало смысла в таком количестве значащих цифр, если всё равно делаешь float. И ведь в math.h есть M_PI.

i-rinat ★★★★★
()
Ответ на: комментарий от Int64

Некоторые меняю

И это работает? Я имею в виду, если в одном модуле меняешь во время исполнения, в другом видно изменения?

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Да, все потому-что у меня и исходные файлы cpp и h все инклудятся в MainSFML.cpp, я знаю что это не правильно, и поэтому сейчас сел все переписывать. Ну и хочется весь код прокомментировать, чтобы было удобно с ним работать, а то уже сейчас теряюсь.

Int64 ★★★
() автор топика
Последнее исправление: Int64 (всего исправлений: 1)
Ответ на: комментарий от Int64

все инклудятся в MainSFML.cpp, я знаю что это не правильно

Прикольно. Unity-builds, так в Firefox'е делают. Sqlite так же собирается, только они называют это amalgamation.

i-rinat ★★★★★
()

Много new/delete в к-торах и д-торах. умные указатели в помощь.
Не вижу смысла в pthread, используй уже std::thread, или ты сохраняешь совместимость с с++03 и boost тащить не хочешь?

anonymous
()
Ответ на: комментарий от i-rinat

А зачем так делать? Я так сделал потому-что только начал C++ изучать, и не разбирался в нем почти, до этого долго программировал на Delphi, только последние 4 года на С++ сижу.

Int64 ★★★
() автор топика

Стоит прогонять через статические анализаторы, типа cppcheck:

[Engine/src/EditableObject.cpp:616]: (error) Reference to auto variable returned.
[gapi/Material.h:119]: (style) Class 'BaseMaterial' is unsafe, 'BaseMaterial::Uniforms' can leak by wrong usage.
[gapi/src/Sprite.cpp:11]: (error) Instance of 'DataRender' object is destroyed immediately.
[gapi/src/Sprite.cpp:36]: (error) Instance of 'DataRender' object is destroyed immediately.
[UI/src/UIStdCtrls.cpp:1169]: (error) When i==wText.size(), wText[i] is out of bounds.
[Utils.h:148]: (error) Uninitialized variable: res
i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

boost тащить не хочется, pthread я уже и не помню зачем подключал. В SFML есть свои классы для реализации многопоточности.

Int64 ★★★
() автор топика
Ответ на: комментарий от i-rinat

Никогда не пользовался статическими анализаторами, спасибо за наводку ))

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64

А зачем так делать?

Это ускоряет сборку и может дать небольшой прирост к производительности. Сборка ускоряется за счёт того, что заголовки парсятся один раз для такого unity-block, вместо многих раз для каждого отдельного cpp-файла. Плюс у компилятора «перед глазами» больше возможностей оптимизаций и инлайнинга. Отсюда прирост в производительности.

i-rinat ★★★★★
()

Я предпочитаю инклюдить только то, что нужно в данной единице трансляции.

Сторонний фреймворк всегда лежит в своей директории где-то в third-party/

Если используется precompiled header, то можно в нем собрать все хедеры, которые используются в проекте и которые не меняются часто (хедеры фреймворков/библиотек).

Никаких using namespace std, только явное указание неймспейса (std::vector<>).

andreyu ★★★★★
()
Ответ на: комментарий от i-rinat

Так стоит ли мне тогда все на cmake переносить, хотя все же прирост производительности лучше делать алгоритмическим путем, а как на счет удобства?

Int64 ★★★
() автор топика
Ответ на: комментарий от andreyu

Ясно, уберу namespace std. А где лучше хранить все глобальные переменные, иногда нужны, например: windowWidth, windowHeight

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64

прирост производительности лучше делать алгоритмическим путем

Конечно же сортировку пузырьком так не ускорить.

а как на счет удобства

А это личные предпочтения автора. Как нравится, так и делаешь.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Мне еще хотелось бы со временем подключить других людей к разработке, так что хотелось бы какое-то универсальное решение )

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64

Ясно, уберу namespace std.

Я не настаиваю, просто мое предпочтение.

А где лучше хранить все глобальные переменные, иногда нужны, например: windowWidth, windowHeight

Может посмотреть в сторону синглтона?

andreyu ★★★★★
()
Ответ на: комментарий от buddhist

Но на данный момент очень сырая, надо пилить и пилить ее )

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64

По сабжу: посмотрел твои скрипты сборки — глаз радуется, может не надо пока тащить всякие симейки? Или требуется значительное усложнение?

buddhist ★★★★★
()
Ответ на: комментарий от buddhist

хм, а я думал наоборот, так не тру ) и хотел сделать как лучше для возможных будущих пользователей

Int64 ★★★
() автор топика
Ответ на: комментарий от andreyu

Синглтон, это на подобие такого?

/* Global parameters */

class Global {
public:
	
	/* Window */

	int screenWidth  = 0;
	int screenHeight = 0;
	int windowWidth  = 0;
	int windowHeight = 0;

};

Int64 ★★★
() автор топика
Ответ на: комментарий от i-rinat

заголовки парсятся один раз

На практике того же можно добиться форвард декларэйшынами, нормальным разделением интерфейса (чтоб заголовки не править каждый раз) от реализации (чтоб не инклудить cpp) и понижением связности между единицами конпеляции (например, пимплами). Потом читать и менять будет легшэ. А песни про оптимизации (или про «оверхэд!111») начинать петь, после профайлинга действительно узких мест. «Прирост производительности» может не стоить геморроя с правкой сорцов через месяц-два :)

slackwarrior ★★★★★
()
Ответ на: комментарий от Int64

Пока там сборка на том уровне, что в твоих скриптах, нет смысла особо заморачиваться со сложными системами сборки. Текущий вариант, к примеру, работает везде, где есть шелл, то есть под каким-нибудь MinGW проблем не будет. А cmake придется еще и ставить.

buddhist ★★★★★
()
Ответ на: комментарий от slackwarrior

может не стоить геморроя с правкой сорцов через месяц-два

Ну так unity builds добавляют параллельно к обычной сборке, никто не делает их основными.

В одном из двух видео с CppCon человек из Ubisoft минут 15 распинался по поводу того, как у них это организовано. Это рассказывать долго, не то что реализовывать. Там какие-то костыли с распределённым аналогом ccache, сборкой-разборкой этих unity, если изменилась только часть исходников. У них машины одних разработчиков в фоне компилируют задачи от других разработчиков. И ещё какие-то трюки.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Я признаю это как способ, когда действительно бывает выгода (желательно, измеренная) :) Игрушки при переносе на мобилки любят делать вкомпиливая все зависимости в один большой бинарь (и не статик линковкой либ, а включением сорцов сторонних либ, да, в одну единицу трансляции), но там обычно достаточно все компактно, чтоб в голове одного человека помещалось :) Если профит на уровне погрешности - лучше так не делать. (Особенно за бесплатно :))

slackwarrior ★★★★★
()
Ответ на: комментарий от slackwarrior

Сейчас пока сделаю просто через баш, но чтобы можно было потом легко перенести в cmake, если нужно будет, все пихать в один файл и инклудить cpp файлы не собираюсь.

Int64 ★★★
() автор топика
Ответ на: комментарий от slackwarrior

Если профит на уровне погрешности - лучше так не делать.

In addition to making SQLite easier to incorporate into other projects, the amalgamation also makes it run faster. Many compilers are able to do additional optimizations on code when it is contained with in a single translation unit such as it is in the amalgamation. We have measured performance improvements of between 5 and 10% when we use the amalgamation to compile SQLite rather than individual source files. The downside of this is that the additional optimizations often take the form of function inlining which tends to make the size of the resulting binary image larger.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Еще вопрос, есть у меня своя реализация файловой системы: https://github.com/sysint64/e2dit/blob/master/fs.h
она еще не дописана, ну так вот я и думаю, может лучше взять boost, но она тяжелая очень, и может лучше доделать свой велосипед )

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64

fs.h

#L427

может лучше взять boost, но она тяжелая очень

Я бы брал готовые библиотеки по возможности. У широко используемых библиотек есть неоспоримый плюс: их больше тестируют.

i-rinat ★★★★★
()
Ответ на: комментарий от Int64

дык не надо ж брать весь буст, только filesystem

gavlig ★★★
()
Ответ на: комментарий от Int64

Синглтон, это на подобие такого?

Да, только нужен статический метод, по которому вы можете получить инстанс объекта (даю набросок, его использовать не стоит; почитайте про этот паттерн):

class Global
{
public:
   static Global* getInstance()
   {
      static Global* me = 0;
      if(!me)
      {
         me = new Global();
      }
      return me;
   }
};

Global* global = Global::getInstance();
global->my_global_variable = some_value;
andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Уже начал немного по другому, сделал: https://github.com/sysint64/e2dit/blob/redesign/src/system/application.h
и у класса Core в конструктор передаю потом этот класс: Core (Application *_app);
Наверное стоит просто немного переписать этот класс под синглтон, сейчас уже читаю )
пока что создал новую ветку с переделкой исходников в читабельный вид: https://github.com/sysint64/e2dit/tree/redesign

Int64 ★★★
() автор топика
Ответ на: комментарий от andreyu

Кстати, то что вы описали - это синглтон Майерса, почему не стоит использовать ваш пример, в википедии описано точно так же, а на C++11 этот вариант потокобезопасен.

Int64 ★★★
() автор топика
Последнее исправление: Int64 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.