CPlusPlus for Gideros Studio Help

Revision as of 19:17, 21 November 2022 by MoKaLux (talk | contribs) (pathfileexists)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Here you will find various resources to help learn C++ for people who wish to help with Gideros Studio development.

WIN32

KNOWNFOLDERID

platform-win32.cpp

refs:

C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp


Convert wstring <-> string

platform-win32.cpp

refs:

C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp

#include <locale> // new 20221014 XXX
#include <codecvt> // new 20221014 XXX

...

std::wstring s2ws(const std::string& str)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.from_bytes(str);
}

std::string ws2s(const std::wstring& wstr)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.to_bytes(wstr);
}


win32 minimum, maximum screen size

platform-win32.cpp

refs:

C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp


win32 LFS problem with separator

Recent changes to path handling (most likely [0]) caused AssetCatalogTest.create_catalog_after_loading_file to fail on WIN32.

The test relied on the resulting path to be joined with "/" as a path separator. The resulting path used both forward and back-slashes. While these do work for some API's on WIN32, mixing both in a file path isn't expected behavior in most cases, so update the tests to use native slash direction for file-paths.

 * \note If you want a trailing slash, add `SEP_STR` as the last path argument,
 * duplicate slashes will be cleaned up.
 */
size_t BLI_path_join(char *__restrict dst, size_t dst_len, const char *path, ...)
#  define SEP '\\'
#  define ALTSEP '/'
#  define SEP_STR "\\"
#  define ALTSEP_STR "/"
#else
#  define SEP '/'
#define SEP_CHR     '#'
#define SEP_STR     "#"

#define EPS 0.001

#define UN_SC_KM    1000.0f
#define UN_SC_HM    100.0f
      str_tmp, TEMP_STR_SIZE, "*%.9g" SEP_STR, unit->scalar / scale_pref);

  if (len_num > len_max) {
    len_num = len_max;
  }

  if (found_ofs + len_num + len_move > len_max) {


openFileDialog

platform-win32.cpp

refs:

#include <wchar.h> // new 20221026 XXX
...
        }else if ((strcmp(what, "openDirectoryDialog") == 0)
                || (strcmp(what, "openFileDialog") == 0)
                || (strcmp(what, "saveFileDialog") == 0))
        {
        	/* TODO parse extension :-( */
            // for win32 args ("title|path|extensions//help") is only 1 arg
            // unlike Qt which seems to cut the | into different args
            if(args.size() == 1){ // do we need to deal with "help" as arg or leave it to Qt?
                // we cut the args
                std::wstring s=ws(args[0].s.c_str()); // "Title|c:\\tmp|Text (*.txt);; Image (*.png)"
                size_t index = s.find(L"|");
                size_t index2 = s.find(L"|", index+1);
                std::wstring title = s.substr(0, index);
                std::wstring place = s.substr(index+1, index2-index-1);
                std::wstring extension = s.substr(index2+1);
//                printf("t p e:\n %ls\n %ls\n %ls\n", title.c_str(),place.c_str(),extension.c_str()); // TEST OK

                DWORD dwFlags; // new 20221028 XXX
                HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
                if (SUCCEEDED(hr))
                {
                    if (strcmp(what, "openDirectoryDialog") == 0){
                        /* TO DO */
                        /*--------------------------------------------------*/
                    }else if (strcmp(what, "openFileDialog") == 0){
                        IFileOpenDialog *pFile;
                        COMDLG_FILTERSPEC fileTypes[] = /* TODO parse from wstring extension :-( */
                        {
                            { L"Text Documents", L"*.txt" },
                            { L"All Files", L"*.*" },
                        };

                        // Create the FileOpenDialog object.
                        hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, 
                                IID_IFileOpenDialog, reinterpret_cast<void**>(&pFile));
                        if (SUCCEEDED(hr))
                        {
                            // get/set options
                            pFile->GetOptions(&dwFlags);
                            pFile->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
                            pFile->SetFileTypes(ARRAYSIZE(fileTypes), fileTypes); // SEE ABOVE fileTypes
                            pFile->SetFileTypeIndex(1); // index starts at 1
//                            pFile->SetDefaultExtension(L"obj;fbx"); // XXX
                            hr = pFile->SetTitle(title.c_str()); // need more check?

                            // set starting folder
                            IShellItem *pItem = NULL;
                            hr = SHCreateItemFromParsingName(place.c_str(), NULL, IID_IShellItem, (LPVOID *)&pItem);
                            if (SUCCEEDED(hr))
                            {
                                pFile->SetFolder(pItem);
                                pItem->Release();
                                pItem = NULL;
                            }

                            // Show the Open dialog box.
                            hr = pFile->Show(NULL);
                            // Get the file name from the dialog box.
                            if (SUCCEEDED(hr))
                            {
                                IShellItem *pItem;
                                hr = pFile->GetResult(&pItem);
                                if (SUCCEEDED(hr))
                                {
                                    PWSTR pszFilePath;
                                    hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
                                    if (SUCCEEDED(hr))
                                    {
                                        r.type=gapplication_Variant::STRING;
                                        r.s=us(pszFilePath);
                                        rets.push_back(r);

                                        CoTaskMemFree(pszFilePath);
                                    }
                                    pItem->Release();
                                }
                            }
                            pFile->Release();
                        }
                        CoUninitialize();
                        /*--------------------------------------------------*/
                    }else if (strcmp(what, "saveFileDialog") == 0){
                        /* TO DO */
                        /*--------------------------------------------------*/
                    }
                }
            }
            /*------------------------------------------------------------------*/
        }else if (strcmp(what, "temporaryDirectory") == 0)

openFileDialog Latest

platform-win32.cpp (updated and working piece of code)

Added:

  • append file extension to saved files (1st extension from filters)
        }else if ((strcmp(what, "openDirectoryDialog") == 0)
                || (strcmp(what, "openFileDialog") == 0)
                || (strcmp(what, "saveFileDialog") == 0))
            {
            if(args.size() <= 2){
                /* INFO SHOWN IN GIDEROS STUDIO DEBUGGER, IMPLEMENTED IN QT, NOT NEEDED HERE? */
            }
            else
            {
                std::wstring title = ws(args[0].s.c_str());
                std::wstring place = ws(args[1].s.c_str());
                std::vector<std::pair<std::wstring,std::wstring>> filters;
                if (args.size()>=3) {
                	std::wstring ext = ws(args[2].s.c_str());
                	while (!ext.empty()) {
                    	std::wstring next;
                		size_t semicolon=ext.find(L";;");
                		if (semicolon!=std::wstring::npos) {
                			next=ext.substr(semicolon+2);
                			ext=ext.substr(0,semicolon);
                		}
                		size_t p1=ext.find_first_of(L'(');
                		size_t p2=ext.find_last_of(L')');
                		if ((p1!=std::wstring::npos)&&(p2!=std::wstring::npos)&&(p2>p1))
                		{
                			//Valid filter, extract label and extensions
                			std::wstring label=ext.substr(0,p1);
                			std::wstring exts=ext.substr(p1+1,p2-p1-1);
                			//QT uses space for extensions separator, while windows expects semicolon. Convert them.
                			std::replace(exts.begin(),exts.end(),L' ',L';');
                			filters.push_back(std::pair<std::wstring,std::wstring>(label,exts));
                		}
                		ext=next;
                	}
                }

                DWORD dwFlags;
                HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
                if (SUCCEEDED(hr))
                {
                    COMDLG_FILTERSPEC *fileTypes=new COMDLG_FILTERSPEC[filters.size()];
                    for (size_t i=0;i<filters.size();i++) {
                    	fileTypes[i].pszName=filters[i].first.c_str();
                    	fileTypes[i].pszSpec=filters[i].second.c_str();
                    }
                    IFileDialog *pFile;
					if (strcmp(what, "saveFileDialog") == 0)
                        hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_ALL,
                                IID_IFileSaveDialog, reinterpret_cast<void**>(&pFile));
					else
                        hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
                                IID_IFileOpenDialog, reinterpret_cast<void**>(&pFile));
					if (SUCCEEDED(hr))
					{
						bool isFolder=(strcmp(what, "openDirectoryDialog") == 0);
						// get/set options
						pFile->GetOptions(&dwFlags);
						pFile->SetOptions(dwFlags | FOS_FORCEFILESYSTEM | (isFolder?FOS_PICKFOLDERS:0));
						if (!isFolder) {
							pFile->SetFileTypes(filters.size(), fileTypes);
							pFile->SetFileTypeIndex(1); // index starts at 1
							//pFile->SetDefaultExtension(L"obj;fbx"); // append default extension
                            //printf("* fileTypes *, set default extension to %ls\n", fileTypes[0].pszSpec); OK
							pFile->SetDefaultExtension(fileTypes[0].pszSpec); // append default 1st extension
						}
						hr = pFile->SetTitle(title.c_str()); // need more check?

						// set starting folder
						IShellItem *pItem = NULL;
						hr = SHCreateItemFromParsingName(place.c_str(), NULL, IID_IShellItem, (LPVOID *)&pItem);
						if (SUCCEEDED(hr))
						{
							pFile->SetFolder(pItem);
							pItem->Release();
							pItem = NULL;
						}

						// Show the Open dialog box.
						hr = pFile->Show(NULL);
						// Get the file name from the dialog box.
						if (SUCCEEDED(hr))
						{
							IShellItem *pItem;
							hr = pFile->GetResult(&pItem);
							if (SUCCEEDED(hr))
							{
								PWSTR pszFilePath;
								hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
								if (SUCCEEDED(hr))
								{
									r.type=gapplication_Variant::STRING;
									r.s=us(pszFilePath);
									rets.push_back(r);

									CoTaskMemFree(pszFilePath);
								}
								pItem->Release();
							}
						}
						pFile->Release();
					}
	                CoUninitialize();
	                delete[] fileTypes;
                }
            }
            /*------------------------------------------------------------------*/
        }else if (strcmp(what, "temporaryDirectory") == 0)


Locate first occurrence of character in wide string

platform-win32.cpp

refs:

std::wstring gs=ws(args[0].s.c_str()); // "Title|C:/tmp/|Text (*.txt);; Image (*.png)"
size_t index = gs.find(L"|");
size_t index2 = gs.find(L"|", index+1);
printf("args0: %ls\n", gs.c_str()); // output: Title|C:/tmp/|Text (*.txt);; Image (*.png)
printf("indices: %d, %d\n", index,index2); // output 5, 13
std::wstring title = gs.substr(0, index);
std::wstring path = gs.substr(index+1, index2-index-1);
std::wstring exts = gs.substr(index2+1);
printf("t p e:\n %ls\n %ls\n %ls\n", title.c_str(),path.c_str(),exts.c_str()); // Title C:/tmp/ Text (*.txt);; Image (*.png)


application:getKeyboardModifiers()

platform-win32.cpp

refs:

if(GetAsyncKeyState(VK_LSHIFT) & 0x8000)
    ; // left shift is currently down


mkDir

platform-win32.cpp

Tested and seems ok :-)

refs:

        }else if (strcmp(what, "mkDir") == 0)
        {
            // new 20221114 XXX
            std::wstring dir = ws(args[0].s.c_str());
            if (_wmkdir(dir.c_str()) == 0)
                printf("mkDir OK: %S\n", dir.c_str()); // can be useful for the w32 console
            else
                printf("mkDir failed or Dir may already exist: %S\n", dir.c_str()); // can be useful for the w32 console
            /*------------------------------------------------------------------*/
        }else if (strcmp(what, "documentDirectory") == 0)


pathfileexists

platform-win32.cpp

Tested and seems ok but not sure about what the return value should be :-/ and we can also check for access mode!

refs:

        }else if (strcmp(what, "pathfileexists") == 0) // new 20221116 XXX
        {
            if (args.size() > 0) {
                std::wstring path = ws(args[0].s.c_str());
                int retValue;
                if (_waccess(path.c_str(), 0) == 0) { // modes: 0=Existence only, 2=Write-only, 4=Read-only, 6=Read and write
                    // path exists
                    retValue = 1;
                } else {
                    retValue = 0;
                }
                r.type=gapplication_Variant::DOUBLE;
                r.d=retValue;
                rets.push_back(r);
            }
            /*------------------------------------------------------------------*/
        }else if ((strcmp(what, "openDirectoryDialog") == 0)

pathfileexists Qt

platform-qt.cpp

QFile Class seems to be "kind of" the equivalent?

refs:

bool QFile::exists(const QString &fileName) Returns true if the file specified by fileName exists; otherwise returns false. Note: If fileName is a symlink that points to a non-existing file, false is returned.

I will need to mix this and _waccess.

WM_GETMINMAXINFO

win32.cpp

WIP

refs:


LoadCursorA

platform-win32.cpp

WIP

refs:

    else { // SET
        if (strcmp(what, "cursor") == 0)
        {
        	/* TODO */
            std::string &shape = args[0].s;
//            QStringList acceptedValue;
//            acceptedValue << "arrow" << "upArrow" << "cross" << "wait" << "IBeam";
//            acceptedValue << "sizeVer" << "sizeHor" << "sizeBDiag" << "sizeFDiag" << "sizeAll";
//            acceptedValue << "blank" << "splitV" << "splitH" << "pointingHand" << "forbidden";
//            acceptedValue << "whatsThis" << "busy" << "openHand" << "closedHand" << "dragCopy";
//            acceptedValue << "dragMove" << "dragLink";
            HCURSOR cursor;
            if (shape == "arrow") {
                printf("** cursor arrow\n");
                cursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
                SetCursor(cursor);
            } else if (shape == "upArrow") {
                printf("** cursor uparrow\n"); // LUA DEBUG OK BUT ARROW SHAPE DOESN'T CHANGE :-(
                cursor = LoadCursorA(NULL, (LPCSTR)IDC_UPARROW);
                SetCursor(cursor);
            }
            /*------------------------------------------------------------------*/
        }else if (strcmp(what, "windowPosition") == 0)


CBUMP

the TODOs

bump.cpp

static bool rect_getSegmentIntersectionIndices(double x, double y, double w,
		double h, double x1, double y1, double x2, double y2, double &ti1,
		double &ti2, double &nx1, double &ny1, double &nx2, double &ny2) {
	//ti1, ti2 = ti1 or 0, ti2 or 1 TODO
	double dx = x2 - x1;
	double dy = y2 - y1;
...
static bool rect_detectCollision(double x1, double y1, double w1, double h1,
		double x2, double y2, double w2, double h2, double goalX, double goalY,
		Collision &col) {
	//goalX = goalX or x1 TODO
	//goalY = goalY or y1

	double dx = goalX - x1, dy = goalY - y1;
...

It is time to do the TODOs ;-)