ares-openbsd/hiro/components.hpp

115 行
2.8 KiB
C++
Raw パーマリンク 通常表示 履歴

/* hiro components
*
* By commenting out lines below, individual components of hiro can be disabled.)
* This can be useful to avoid dependencies (eg GTK+ relies on GtkSourceView for SourceEdit.)
* It's also very useful for porting hiro to new targets; or performing major core changes.
*
* Note that the core classes (Application, Window, Sizable, etc) have circular dependencies.
* Disabling only certain core pieces will result in compilation errors.
* As such, this file is really only meant for disabling individual widgets or menu items.
*/
#define Hiro_Color
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 11:08:26 +09:00
#define Hiro_Gradient
#define Hiro_Alignment
#define Hiro_TextCursor
#define Hiro_Position
#define Hiro_Size
#define Hiro_Geometry
#define Hiro_Font
#define Hiro_MouseCursor
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 11:08:26 +09:00
#define Hiro_Application
#define Hiro_Desktop
#define Hiro_Monitor
#define Hiro_Keyboard
#define Hiro_Mouse
#define Hiro_BrowserWindow
#define Hiro_MessageWindow
#define Hiro_Attribute
#define Hiro_Object
#define Hiro_Group
#define Hiro_Hotkey
#define Hiro_Timer
#define Hiro_Window
#define Hiro_StatusBar
#define Hiro_MenuBar
#define Hiro_PopupMenu
#define Hiro_Action
#define Hiro_Menu
#define Hiro_MenuSeparator
#define Hiro_MenuItem
#define Hiro_MenuCheckItem
#define Hiro_MenuRadioItem
#define Hiro_Sizable
#define Hiro_Widget
#define Hiro_Button
#define Hiro_Canvas
#define Hiro_CheckButton
#define Hiro_CheckLabel
#define Hiro_ComboButton
#define Hiro_ComboEdit
#define Hiro_Console
#define Hiro_Frame
#define Hiro_HexEdit
#define Hiro_HorizontalScrollBar
#define Hiro_HorizontalSlider
#define Hiro_IconView
#define Hiro_Label
#define Hiro_LineEdit
#define Hiro_ProgressBar
#define Hiro_RadioButton
#define Hiro_RadioLabel
//#define Hiro_SourceEdit //added via GNUmakefile
#define Hiro_TabFrame
#define Hiro_TableView
#define Hiro_TextEdit
#define Hiro_TreeView
#define Hiro_VerticalScrollBar
#define Hiro_VerticalSlider
#define Hiro_Viewport
//platform-specific exclusions
#if defined(HIRO_WINDOWS) || defined(HIRO_COCOA) || defined(HIRO_QT)
#undef Hiro_ComboEdit
#undef Hiro_Console
#undef Hiro_IconView
#undef Hiro_SourceEdit
#endif
//extensions
#define Hiro_FixedLayout
#define Hiro_HorizontalLayout
#define Hiro_VerticalLayout
Update to v106r47 release. byuu says: This is probably the largest code-change diff I've done in years. I spent four days working 10-16 hours a day reworking layouts in hiro completely. The result is we now have TableLayout, which will allow for better horizontal+vertical combined alignment. Windows, GTK2, and now GTK3 are fully supported. Windows is getting the initial window geometry wrong by a bit. GTK2 and GTK3 work perfectly. I basically abandoned trying to detect resize signals, and instead keep a list of all hiro windows that are allocated, and every time the main loop runs, it will query all of them to see if they've been resized. I'm disgusted that I have to do this, but after fighting with GTK for years, I'm about sick of it. GTK was doing this crazy thing where it would trigger another size-allocate inside of a previous size-allocate, and so my layouts would be halfway through resizing all the widgets, and then the size-allocate would kick off another one. That would end up leaving the rest of the first layout loop with bad widget sizes. And if I detected a second re-entry and blocked it, then the entire window would end up with the older geometry. I started trying to build a message queue system to allow the second layout resize to occur after the first one completed, but this was just too much madness, so I went with the simpler solution. Qt4 has some geometry problems, and doesn't show tab frame layouts properly yet. Qt5 causes an ICE error and tanks my entire Xorg display server, so ... something is seriously wrong there, and it's not hiro's fault. Creating a dummy Qt5 application without even using hiro, just int main() { TestObject object; } with object performing a dynamic\_cast to a derived type segfaults. Memory is getting corrupted where GCC allocates the vtables for classes, just by linking in Qt. Could be somehow related to the -fPIC requirement that only Qt5 has ... could just be that FreeBSD 10.1 has a buggy implementation of Qt5. I don't know. It's beyond my ability to debug, so this one's going to stay broken. The Cocoa port is busted. I'll fix it up to compile again, but that's about all I'm going to do. Many optimizations mean bsnes and higan open faster. GTK2 and GTK3 both resize windows very quickly now. higan crashes when you load a game, so that's not good. bsnes works though. bsnes also has the start of a localization engine now. Still a long way to go. The makefiles received a rather substantial restructuring. Including the ruby and hiro makefiles will add the necessary compilation rules for you, which also means that moc will run for the qt4 and qt5 targets, and windres will run for the Windows targets.
2018-07-14 12:59:29 +09:00
#define Hiro_TableLayout
Update to v106r100 release. byuu says: Another thirteen hours ... Concerta is a hell of a drug. Okay, so this is a partial merging of Screwtape and bun's suggestions for a multi-pane layout. The configuration manager shows the list of systems on the left, and you can choose to create a new system in the right pane, or to see (read-only) the current connections of a given system entry. For right now, there's just a simple logo display on the right when no systems are selected and you're not in create mode. I imagine it will make more sense to list the systems on the right when not showing a specific system connections list, but ... I wanted to put the icon there for now. To do that, I wrote a new nall::image function, shrink(), which detects all entirely blank/transparent rows/columns on all four sides of an image, and then crops them out. I could have just used Imagemagick on the icon.png file, but ... overkill is more fun. My thoughts were, maybe in the future, we can populate it as a kind of "home" screen with some more things. Have to think about it. The system manager window shows the connections on the left, and you can edit either port↔peripheral connections or input mappings on the right. And in the future, settings and other such things as well. The system manager also has a "blank" panel, but this time it's just a disabled, empty TreeView (so that the frame matches the other panels.) We could put anything here as well in the future ... There's new hiro classes, HorizontalResizeGrip and VerticalResizeGrip. The former is used to let you resize the two panels. I burned a lot of time reimplementing the horizontal scroll bar display in GtkTreeView, because GTK's implementation was busted, ignored icon indentations, and showed the scrollbar way too early. The tree views now render little L bracket things to help show indentation a bit better. Unfortunately my GTK themes can't do this even with the extenders visible, so this is the best I can do in a cross-platform manner for now ... If we decide to give up on tree views ... we will have to lose the icons (and the chance of any nicer node-specific icons in the future), because the TableViewItem icons always appear at the far left. I might consider it anyway because I really don't want to port TreeView to Windows, Qt, and MacOS. I turned back on the GTK alternating row colors for a bit, to make the input mapping panel a bit easier to read. I cleaned up a lot of the SNES core code as well. The Super Multitap is back, and functions like a real Super Multitap for the first time ever. There is the possibility of a controller that passes through the iobit lines to PIO d6/d7, but for now, the only controller we emulate with extra ports (save for maybe the dual Justifier) is the Multitap, and it doesn't pass through the iobits to its connected children, so for now I'm just having anything other than controller ports 1&2 return 0 from iobit reads, and ignore iobit writes. The ControllerPorts implement wrappers for the Controller functions (iobit, data, latch) so that the Controller* device object can be a nullptr. Expansions are connectable again. There's a new Thread::destroy() to both release a cothread_t and remove it from the scheduler threads list. I still regrettably have to also remove the threads from the cpu.coprocessors/cpu.peripherals vectors (speaking of, I should double-check that the peripherals do this right.) All of the coprocessors have been updated to properly do all of this, and handle thread attach/detach inside their own unload/power functions, instead of in System/Cartridge::power,unload. The Satellaview maps data onto and off the SNES bus, but ultimately this should be okay because the expansion port isn't hot-swappable. If you forcefully do it anyway, it should still work since nothing else maps to those ranges except for the 21fx. I updated hiro's setAlignment functions to replace the newer setPlacement with something even more flexible. Love it or hate it, higan now places the system manager window in the center of the screen, and when you power on a system, it centers the video, and then moves the system manager to the left of the video output. When you close the video output, it acts like an unload event and moves the system manager back. If the system manager is either minimized or maximized, it won't move it on power on (though currently you can't power the system on with the system manager minimized, but maybe later with a hotkey ...) When you close the video window, it'll unminimize the system manager if you did that, and then center it ... unless it was maximized. Unserializing node.bml tables got a lot more strict. Now only Setting values and Property values can be unserialized into the root tree, and only when both the type (identity) and name of the node matches up. This should hopefully help to prevent incompatibilities as the node.bml structure changes. If you right-click on a port, you can change the path it looks for things in. This is a bit hidden, and the port connection panel should really tell you where it's looking as well. We'll get there. I'm sure there's a lot more, but that's all I can remember right now.
2019-02-07 20:04:24 +09:00
#if defined(Hiro_Timer) && defined(Hiro_Canvas)
#define Hiro_HorizontalResizeGrip
#define Hiro_VerticalResizeGrip
#endif
#if defined(Hiro_TableView)
#define Hiro_ListView
#endif
#if defined(Hiro_Button) && defined(Hiro_Canvas) && defined(Hiro_Label)
#define Hiro_MessageDialog
Update to v106r96 release. byuu says: Templates now import to the user data folders, so you can create multiple gamepads with distinct mappings ... or at least, you will be able to. Things have progressed enough that you can map keyboard inputs to play Zelda 3 a bit now. But if you close the emulator, the assignment device will be lost. Right now, it's serializing things to the root.bml document instead of to individual peripherals, and it's also not properly serializing/unserializing the HID object from ruby. The old naming of program, emulator, emulators didn't match the new design where Program wasn't the center of higan anymore (the configuration manager precedes it), and Emulator has become higan, so that's been renamed to emulator, interface, interfaces. Some new work on hiro and nall: MessageDialog - when dismissing, set the response to the last button - add dismissed() function NameDialog - new class for create / rename file/folder dialog boxes BrowserDialog - add create (folder), rename, and delete support directory: - add copy() function - fix sorting of folders to ignore trailing / string: - added string::from<T> and string.to<T> for object binding - requires string::operator bool() to return true when capacity() == 0 ... The last one is going to be really contentious, but ... oh my gods I am in love with it already. So for an example: auto x = shared_pointer_make<Foo>(); node->setProperty("id", string::from(x)); if(auto y = node->property("id")) y.to<shared_pointer<Foo>>()->bar(); The idea is to add another special case in nall::string, where when the capacity is zero, the new _hold pointer holds a type-erasing object. This object is set via string::from<T>(), and extracted via string.to<T>(). The capacity is always >= 23 normally, due to SSO, so it's okay to special-case zero. _hold doesn't make the string take any more space ... with SSO of 24 and two pointers before, we're just using up the rest of the space we already had. The total size of strings is still 32. Although at some point I'll probably make it 40 for 64-bit size/capacity, but that's not super pressing right now. Anyway ... why in the hell would I do this? Well, hiro has the Object::property/setProperty system for keeping a set (red-black tree) of name:value mappings. And higan adopted the same system for its Node objects. The name is obviously a string, but the value is also a string. Why a string? Because it's the easiest to serialize, and can be converted to and from any data type: booleans, integers, floats, strings, pointers ... and all of those implicitly convert into strings for you, so you setProperty("name", 3.7) is just fine. But it can't hold objects. Even if you allocate a new pointer and store it in the string, it'll end up leaking if you don't make sure to extract the pointer and delete it before the string goes away. I really didn't want to move the property system to any<T> types because they are such a massive pain in the ass to use in every case. It would make serializing/unserializing Property structures in Node elements way more painful, too. And any<T> basically requires heap allocation for absolutely any value. nall::string will only allocate memory when the string size is > 24 (or now, if you use the new string::from support.) Now obviously, string::from has a caveat: you can't serialize it. You can copy a string holding a T object to another safely, but once you try and print it into a text document, the string value will be empty, and when you try and read a string back from the text file, it's gonna also be empty. Even if we extracted the pointer from the string to store, restarting your program would invalidate the pointer anyway. This is a pretty significant win ... for my tree structure in higan's system manager, I can just hold shared_pointer copies of each Node inside each TreeViewItem, and retrieve them directly. No crazy path traversal up and down the tree with lots of string parsing involved. No possibilities for bizarre bugs because the two get out of sync, or the tree paths change in higan, or whatever else. The worst thing that could possibly happen is the shared_pointers between higan::Interface::root() and SystemManager get broken, and SystemManager just stabs at perfectly valid but detached Node objects. No big deal. No problem. In practice that's not going to happen anyway. In implementing this new feature, I realized that my template<typename... P> string(P&&...) constructor was matching instead of string(const string&), so I added a string(string&) constructor, which should in general help the performance of building strings a whole hell of a lot, presumably much more than the tiny tiny hit for the extra checks for the new string::from mode. There's only one thing about string::from that kind of worries me ... explicit string::operator bool() const must necessarily return true when holding a T object, even though the size and capacity are both zero. If we don't do this, the values will be lost in eg setProperty erasing nall::set entries when the assigned value is a blank string. I don't know if this will have unfortunate side effects in other string processing code, but ... in general, I've never used nall::from in any other code, so if there's an issue, we'll find it as we are using nall::from objects. The change should not impact any existing code as such. Lastly, the MessageDialog change ... in way too many places, I do tests like if(MessageDialog() .... question() == "Yes") or (... question() == "No"), but I don't test both Yes and No. So whichever I tested with ==, it'd be false when the MessageDialog were dismissed, and the inverse for !=. Not good. Sometimes it's the difference between deleting a directory recursively or cancelling the operation. I don't think in the history of using hiro I've ever bothered to actually test for .question()=="", so I think this change is really imporant. If the dismissal case is really needed, MessageDialog::dismissed() can be checked now instead. So the next big thing is going to be more advanced tree parsing: it doesn't really matter whether the root tree gets serialized with all the peripheral input values, but we absolutely must serialize each peripheral to its respective folder. And when unserializing the root, we have to go through and unserialize all of the peripherals. Also for input mapping, I have to serialize the hardware HID path + deviceID + vendorID, and then create a binding function that'll scan the root tree for all Input devices and rebind the shared_pointers to the new shared_pointer<HID::Device> instances. But, hopefully, hopefully ... I can get that done in the next WIP.
2019-02-03 16:55:29 +09:00
#define Hiro_NameDialog
#endif
Update to v106r96 release. byuu says: Templates now import to the user data folders, so you can create multiple gamepads with distinct mappings ... or at least, you will be able to. Things have progressed enough that you can map keyboard inputs to play Zelda 3 a bit now. But if you close the emulator, the assignment device will be lost. Right now, it's serializing things to the root.bml document instead of to individual peripherals, and it's also not properly serializing/unserializing the HID object from ruby. The old naming of program, emulator, emulators didn't match the new design where Program wasn't the center of higan anymore (the configuration manager precedes it), and Emulator has become higan, so that's been renamed to emulator, interface, interfaces. Some new work on hiro and nall: MessageDialog - when dismissing, set the response to the last button - add dismissed() function NameDialog - new class for create / rename file/folder dialog boxes BrowserDialog - add create (folder), rename, and delete support directory: - add copy() function - fix sorting of folders to ignore trailing / string: - added string::from<T> and string.to<T> for object binding - requires string::operator bool() to return true when capacity() == 0 ... The last one is going to be really contentious, but ... oh my gods I am in love with it already. So for an example: auto x = shared_pointer_make<Foo>(); node->setProperty("id", string::from(x)); if(auto y = node->property("id")) y.to<shared_pointer<Foo>>()->bar(); The idea is to add another special case in nall::string, where when the capacity is zero, the new _hold pointer holds a type-erasing object. This object is set via string::from<T>(), and extracted via string.to<T>(). The capacity is always >= 23 normally, due to SSO, so it's okay to special-case zero. _hold doesn't make the string take any more space ... with SSO of 24 and two pointers before, we're just using up the rest of the space we already had. The total size of strings is still 32. Although at some point I'll probably make it 40 for 64-bit size/capacity, but that's not super pressing right now. Anyway ... why in the hell would I do this? Well, hiro has the Object::property/setProperty system for keeping a set (red-black tree) of name:value mappings. And higan adopted the same system for its Node objects. The name is obviously a string, but the value is also a string. Why a string? Because it's the easiest to serialize, and can be converted to and from any data type: booleans, integers, floats, strings, pointers ... and all of those implicitly convert into strings for you, so you setProperty("name", 3.7) is just fine. But it can't hold objects. Even if you allocate a new pointer and store it in the string, it'll end up leaking if you don't make sure to extract the pointer and delete it before the string goes away. I really didn't want to move the property system to any<T> types because they are such a massive pain in the ass to use in every case. It would make serializing/unserializing Property structures in Node elements way more painful, too. And any<T> basically requires heap allocation for absolutely any value. nall::string will only allocate memory when the string size is > 24 (or now, if you use the new string::from support.) Now obviously, string::from has a caveat: you can't serialize it. You can copy a string holding a T object to another safely, but once you try and print it into a text document, the string value will be empty, and when you try and read a string back from the text file, it's gonna also be empty. Even if we extracted the pointer from the string to store, restarting your program would invalidate the pointer anyway. This is a pretty significant win ... for my tree structure in higan's system manager, I can just hold shared_pointer copies of each Node inside each TreeViewItem, and retrieve them directly. No crazy path traversal up and down the tree with lots of string parsing involved. No possibilities for bizarre bugs because the two get out of sync, or the tree paths change in higan, or whatever else. The worst thing that could possibly happen is the shared_pointers between higan::Interface::root() and SystemManager get broken, and SystemManager just stabs at perfectly valid but detached Node objects. No big deal. No problem. In practice that's not going to happen anyway. In implementing this new feature, I realized that my template<typename... P> string(P&&...) constructor was matching instead of string(const string&), so I added a string(string&) constructor, which should in general help the performance of building strings a whole hell of a lot, presumably much more than the tiny tiny hit for the extra checks for the new string::from mode. There's only one thing about string::from that kind of worries me ... explicit string::operator bool() const must necessarily return true when holding a T object, even though the size and capacity are both zero. If we don't do this, the values will be lost in eg setProperty erasing nall::set entries when the assigned value is a blank string. I don't know if this will have unfortunate side effects in other string processing code, but ... in general, I've never used nall::from in any other code, so if there's an issue, we'll find it as we are using nall::from objects. The change should not impact any existing code as such. Lastly, the MessageDialog change ... in way too many places, I do tests like if(MessageDialog() .... question() == "Yes") or (... question() == "No"), but I don't test both Yes and No. So whichever I tested with ==, it'd be false when the MessageDialog were dismissed, and the inverse for !=. Not good. Sometimes it's the difference between deleting a directory recursively or cancelling the operation. I don't think in the history of using hiro I've ever bothered to actually test for .question()=="", so I think this change is really imporant. If the dismissal case is really needed, MessageDialog::dismissed() can be checked now instead. So the next big thing is going to be more advanced tree parsing: it doesn't really matter whether the root tree gets serialized with all the peripheral input values, but we absolutely must serialize each peripheral to its respective folder. And when unserializing the root, we have to go through and unserialize all of the peripherals. Also for input mapping, I have to serialize the hardware HID path + deviceID + vendorID, and then create a binding function that'll scan the root tree for all Input devices and rebind the shared_pointers to the new shared_pointer<HID::Device> instances. But, hopefully, hopefully ... I can get that done in the next WIP.
2019-02-03 16:55:29 +09:00
#if defined(Hiro_Button) && defined(Hiro_ComboButton) && defined(Hiro_LineEdit) && defined(Hiro_ListView) && defined(Hiro_MessageDialog) && defined(Hiro_NameDialog)
#define Hiro_BrowserDialog
#endif
Update to v106r96 release. byuu says: Templates now import to the user data folders, so you can create multiple gamepads with distinct mappings ... or at least, you will be able to. Things have progressed enough that you can map keyboard inputs to play Zelda 3 a bit now. But if you close the emulator, the assignment device will be lost. Right now, it's serializing things to the root.bml document instead of to individual peripherals, and it's also not properly serializing/unserializing the HID object from ruby. The old naming of program, emulator, emulators didn't match the new design where Program wasn't the center of higan anymore (the configuration manager precedes it), and Emulator has become higan, so that's been renamed to emulator, interface, interfaces. Some new work on hiro and nall: MessageDialog - when dismissing, set the response to the last button - add dismissed() function NameDialog - new class for create / rename file/folder dialog boxes BrowserDialog - add create (folder), rename, and delete support directory: - add copy() function - fix sorting of folders to ignore trailing / string: - added string::from<T> and string.to<T> for object binding - requires string::operator bool() to return true when capacity() == 0 ... The last one is going to be really contentious, but ... oh my gods I am in love with it already. So for an example: auto x = shared_pointer_make<Foo>(); node->setProperty("id", string::from(x)); if(auto y = node->property("id")) y.to<shared_pointer<Foo>>()->bar(); The idea is to add another special case in nall::string, where when the capacity is zero, the new _hold pointer holds a type-erasing object. This object is set via string::from<T>(), and extracted via string.to<T>(). The capacity is always >= 23 normally, due to SSO, so it's okay to special-case zero. _hold doesn't make the string take any more space ... with SSO of 24 and two pointers before, we're just using up the rest of the space we already had. The total size of strings is still 32. Although at some point I'll probably make it 40 for 64-bit size/capacity, but that's not super pressing right now. Anyway ... why in the hell would I do this? Well, hiro has the Object::property/setProperty system for keeping a set (red-black tree) of name:value mappings. And higan adopted the same system for its Node objects. The name is obviously a string, but the value is also a string. Why a string? Because it's the easiest to serialize, and can be converted to and from any data type: booleans, integers, floats, strings, pointers ... and all of those implicitly convert into strings for you, so you setProperty("name", 3.7) is just fine. But it can't hold objects. Even if you allocate a new pointer and store it in the string, it'll end up leaking if you don't make sure to extract the pointer and delete it before the string goes away. I really didn't want to move the property system to any<T> types because they are such a massive pain in the ass to use in every case. It would make serializing/unserializing Property structures in Node elements way more painful, too. And any<T> basically requires heap allocation for absolutely any value. nall::string will only allocate memory when the string size is > 24 (or now, if you use the new string::from support.) Now obviously, string::from has a caveat: you can't serialize it. You can copy a string holding a T object to another safely, but once you try and print it into a text document, the string value will be empty, and when you try and read a string back from the text file, it's gonna also be empty. Even if we extracted the pointer from the string to store, restarting your program would invalidate the pointer anyway. This is a pretty significant win ... for my tree structure in higan's system manager, I can just hold shared_pointer copies of each Node inside each TreeViewItem, and retrieve them directly. No crazy path traversal up and down the tree with lots of string parsing involved. No possibilities for bizarre bugs because the two get out of sync, or the tree paths change in higan, or whatever else. The worst thing that could possibly happen is the shared_pointers between higan::Interface::root() and SystemManager get broken, and SystemManager just stabs at perfectly valid but detached Node objects. No big deal. No problem. In practice that's not going to happen anyway. In implementing this new feature, I realized that my template<typename... P> string(P&&...) constructor was matching instead of string(const string&), so I added a string(string&) constructor, which should in general help the performance of building strings a whole hell of a lot, presumably much more than the tiny tiny hit for the extra checks for the new string::from mode. There's only one thing about string::from that kind of worries me ... explicit string::operator bool() const must necessarily return true when holding a T object, even though the size and capacity are both zero. If we don't do this, the values will be lost in eg setProperty erasing nall::set entries when the assigned value is a blank string. I don't know if this will have unfortunate side effects in other string processing code, but ... in general, I've never used nall::from in any other code, so if there's an issue, we'll find it as we are using nall::from objects. The change should not impact any existing code as such. Lastly, the MessageDialog change ... in way too many places, I do tests like if(MessageDialog() .... question() == "Yes") or (... question() == "No"), but I don't test both Yes and No. So whichever I tested with ==, it'd be false when the MessageDialog were dismissed, and the inverse for !=. Not good. Sometimes it's the difference between deleting a directory recursively or cancelling the operation. I don't think in the history of using hiro I've ever bothered to actually test for .question()=="", so I think this change is really imporant. If the dismissal case is really needed, MessageDialog::dismissed() can be checked now instead. So the next big thing is going to be more advanced tree parsing: it doesn't really matter whether the root tree gets serialized with all the peripheral input values, but we absolutely must serialize each peripheral to its respective folder. And when unserializing the root, we have to go through and unserialize all of the peripherals. Also for input mapping, I have to serialize the hardware HID path + deviceID + vendorID, and then create a binding function that'll scan the root tree for all Input devices and rebind the shared_pointers to the new shared_pointer<HID::Device> instances. But, hopefully, hopefully ... I can get that done in the next WIP.
2019-02-03 16:55:29 +09:00
#if defined(Hiro_Canvas) && defined(Hiro_Label)
#define Hiro_AboutDialog
#endif