Browse Source

Improved Sound Debug UI, updated ImGui

Thomas Buck 9 years ago
parent
commit
86a7bbab0f

+ 7
- 0
ChangeLog.md View File

2
 
2
 
3
 ## OpenRaider (0.1.3) xythobuz <xythobuz@xythobuz.de>
3
 ## OpenRaider (0.1.3) xythobuz <xythobuz@xythobuz.de>
4
 
4
 
5
+    [ 20140309 ]
6
+    * Removed (unused) SSE support script
7
+    * Added level loading notification in main menu
8
+    * Can now start/stop individual SoundSources
9
+    * Added SoundDetail debug UI, improved SoundSources debug UI
10
+    * Updated imgui to version 1.35
11
+
5
     [ 20140307 ]
12
     [ 20140307 ]
6
     * Can now load all TR3 levels without crashing
13
     * Can now load all TR3 levels without crashing
7
     * Sound Sources now working, with (more or less) proper 3D Sound
14
     * Sound Sources now working, with (more or less) proper 3D Sound

+ 0
- 1
README.md View File

174
 
174
 
175
 * [FindALUT](https://github.com/rpavlik/cmake-modules/blob/master/FindALUT.cmake)
175
 * [FindALUT](https://github.com/rpavlik/cmake-modules/blob/master/FindALUT.cmake)
176
 * [FindSDL2](https://github.com/dhewm/dhewm3/blob/master/neo/sys/cmake/FindSDL2.cmake)
176
 * [FindSDL2](https://github.com/dhewm/dhewm3/blob/master/neo/sys/cmake/FindSDL2.cmake)
177
-* [FindSSE](https://gitorious.org/vc/vc/source/a1d8b9fc31060d870386613cc72319546c850b87:cmake/FindSSE.cmake)
178
 * [GetGitRevisionDescription.cmake](https://github.com/rpavlik/cmake-modules/blob/master/GetGitRevisionDescription.cmake)
177
 * [GetGitRevisionDescription.cmake](https://github.com/rpavlik/cmake-modules/blob/master/GetGitRevisionDescription.cmake)
179
 * [GetGitRevisionDescription.cmake.in](https://github.com/rpavlik/cmake-modules/blob/master/GetGitRevisionDescription.cmake.in)
178
 * [GetGitRevisionDescription.cmake.in](https://github.com/rpavlik/cmake-modules/blob/master/GetGitRevisionDescription.cmake.in)
180
 * [FindGLM] (https://github.com/g-truc/glm/blob/master/util/FindGLM.cmake)
179
 * [FindGLM] (https://github.com/g-truc/glm/blob/master/util/FindGLM.cmake)

+ 0
- 1
TODO.md View File

8
 
8
 
9
 ## Cmake
9
 ## Cmake
10
 
10
 
11
-* Support SSE with other compilers than Clang (src/CMakeLists.txt)
12
 * Visual C++ compiler flags? (CMakeLists.txt)
11
 * Visual C++ compiler flags? (CMakeLists.txt)
13
 * Better test integration
12
 * Better test integration
14
 
13
 

+ 0
- 124
cmake/FindSSE.cmake View File

1
-# Check if SSE instructions are available on the machine where 
2
-# the project is compiled.
3
-
4
-IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
5
-    EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO)
6
-
7
-    # TODO
8
-    set(SSE_FOUND true CACHE BOOL "SSE available on host")
9
-
10
-    STRING(REGEX REPLACE "^.*(sse2).*$" "\\1" SSE_THERE ${CPUINFO})
11
-    STRING(COMPARE EQUAL "sse2" "${SSE_THERE}" SSE2_TRUE)
12
-    IF (SSE2_TRUE)
13
-        set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
14
-    ELSE (SSE2_TRUE)
15
-        set(SSE2_FOUND false CACHE BOOL "SSE2 available on host")
16
-    ENDIF (SSE2_TRUE)
17
-
18
-    # /proc/cpuinfo apparently omits sse3 :(
19
-    STRING(REGEX REPLACE "^.*[^s](sse3).*$" "\\1" SSE_THERE ${CPUINFO})
20
-    STRING(COMPARE EQUAL "sse3" "${SSE_THERE}" SSE3_TRUE)
21
-    IF (NOT SSE3_TRUE)
22
-        STRING(REGEX REPLACE "^.*(T2300).*$" "\\1" SSE_THERE ${CPUINFO})
23
-        STRING(COMPARE EQUAL "T2300" "${SSE_THERE}" SSE3_TRUE)
24
-    ENDIF (NOT SSE3_TRUE)
25
-
26
-    STRING(REGEX REPLACE "^.*(ssse3).*$" "\\1" SSE_THERE ${CPUINFO})
27
-    STRING(COMPARE EQUAL "ssse3" "${SSE_THERE}" SSSE3_TRUE)
28
-    IF (SSE3_TRUE OR SSSE3_TRUE)
29
-        set(SSE3_FOUND true CACHE BOOL "SSE3 available on host")
30
-    ELSE (SSE3_TRUE OR SSSE3_TRUE)
31
-        set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
32
-    ENDIF (SSE3_TRUE OR SSSE3_TRUE)
33
-    IF (SSSE3_TRUE)
34
-        set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host")
35
-    ELSE (SSSE3_TRUE)
36
-        set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
37
-    ENDIF (SSSE3_TRUE)
38
-
39
-    STRING(REGEX REPLACE "^.*(sse4_1).*$" "\\1" SSE_THERE ${CPUINFO})
40
-    STRING(COMPARE EQUAL "sse4_1" "${SSE_THERE}" SSE41_TRUE)
41
-    IF (SSE41_TRUE)
42
-        set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host")
43
-    ELSE (SSE41_TRUE)
44
-        set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
45
-    ENDIF (SSE41_TRUE)
46
-ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
47
-    EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE
48
-        CPUINFO)
49
-
50
-    STRING(REGEX REPLACE "^.*[^S](SSE).*$" "\\1" SSE_THERE ${CPUINFO})
51
-    STRING(COMPARE EQUAL "SSE" "${SSE_THERE}" SSE_TRUE)
52
-    IF (SSE_TRUE)
53
-        set(SSE_FOUND true CACHE BOOL "SSE available on host")
54
-    ELSE (SSE_TRUE)
55
-        set(SSE_FOUND false CACHE BOOL "SSE available on host")
56
-    ENDIF (SSE_TRUE)
57
-
58
-    STRING(REGEX REPLACE "^.*[^S](SSE2).*$" "\\1" SSE_THERE ${CPUINFO})
59
-    STRING(COMPARE EQUAL "SSE2" "${SSE_THERE}" SSE2_TRUE)
60
-    IF (SSE2_TRUE)
61
-        set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
62
-    ELSE (SSE2_TRUE)
63
-        set(SSE2_FOUND false CACHE BOOL "SSE2 available on host")
64
-    ENDIF (SSE2_TRUE)
65
-
66
-    STRING(REGEX REPLACE "^.*[^S](SSE3).*$" "\\1" SSE_THERE ${CPUINFO})
67
-    STRING(COMPARE EQUAL "SSE3" "${SSE_THERE}" SSE3_TRUE)
68
-    IF (SSE3_TRUE)
69
-        set(SSE3_FOUND true CACHE BOOL "SSE3 available on host")
70
-    ELSE (SSE3_TRUE)
71
-        set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
72
-    ENDIF (SSE3_TRUE)
73
-
74
-    STRING(REGEX REPLACE "^.*(SSSE3).*$" "\\1" SSE_THERE ${CPUINFO})
75
-    STRING(COMPARE EQUAL "SSSE3" "${SSE_THERE}" SSSE3_TRUE)
76
-    IF (SSSE3_TRUE)
77
-        set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host")
78
-    ELSE (SSSE3_TRUE)
79
-        set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
80
-    ENDIF (SSSE3_TRUE)
81
-
82
-    STRING(REGEX REPLACE "^.*(SSE4.1).*$" "\\1" SSE_THERE ${CPUINFO})
83
-    STRING(COMPARE EQUAL "SSE4.1" "${SSE_THERE}" SSE41_TRUE)
84
-    IF (SSE41_TRUE)
85
-        set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host")
86
-    ELSE (SSE41_TRUE)
87
-        set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
88
-    ENDIF (SSE41_TRUE)
89
-ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows")
90
-    # TODO
91
-    set(SSE_FOUND    true  CACHE BOOL "SSE available on host")
92
-    set(SSE2_FOUND   true  CACHE BOOL "SSE2 available on host")
93
-    set(SSE3_FOUND   false CACHE BOOL "SSE3 available on host")
94
-    set(SSSE3_FOUND  false CACHE BOOL "SSSE3 available on host")
95
-    set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
96
-ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux")
97
-    set(SSE_FOUND    true  CACHE BOOL "SSE available on host")
98
-    set(SSE2_FOUND   true  CACHE BOOL "SSE2 available on host")
99
-    set(SSE3_FOUND   false CACHE BOOL "SSE3 available on host")
100
-    set(SSSE3_FOUND  false CACHE BOOL "SSSE3 available on host")
101
-    set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
102
-ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
103
-
104
-if(NOT SSE_FOUND)
105
-    MESSAGE(STATUS "Could not find hardware support for SSE on this machine.")
106
-endif(NOT SSE_FOUND)
107
-
108
-if(NOT SSE2_FOUND)
109
-    MESSAGE(STATUS "Could not find hardware support for SSE2 on this machine.")
110
-endif(NOT SSE2_FOUND)
111
-
112
-if(NOT SSE3_FOUND)
113
-    MESSAGE(STATUS "Could not find hardware support for SSE3 on this machine.")
114
-endif(NOT SSE3_FOUND)
115
-
116
-if(NOT SSSE3_FOUND)
117
-    MESSAGE(STATUS "Could not find hardware support for SSSE3 on this machine.")
118
-endif(NOT SSSE3_FOUND)
119
-
120
-if(NOT SSE4_1_FOUND)
121
-    MESSAGE(STATUS "Could not find hardware support for SSE4.1 on this machine.")
122
-endif(NOT SSE4_1_FOUND)
123
-
124
-mark_as_advanced(SSE_FOUND SSE2_FOUND SSE3_FOUND SSSE3_FOUND SSE4_1_FOUND)

+ 1
- 1
include/Menu.h View File

35
 
35
 
36
   protected:
36
   protected:
37
 
37
 
38
-    virtual void showDialog(std::string msg, std::string btn1, std::string btn2,
38
+    virtual void showDialog(std::string msg, std::string btn1, std::string btn2 = "",
39
                             std::function<int (bool state)> callback = std::function<int (bool)>());
39
                             std::function<int (bool state)> callback = std::function<int (bool)>());
40
 
40
 
41
     virtual void ackDialog();
41
     virtual void ackDialog();

+ 5
- 1
include/SoundManager.h View File

13
 class SoundSource {
13
 class SoundSource {
14
   public:
14
   public:
15
     SoundSource(glm::vec3 p, int i, int f)
15
     SoundSource(glm::vec3 p, int i, int f)
16
-        : pos(p), id(i), flags(f), source(-1) { }
16
+        : pos(p), id(i), flags(f), source(-1), playing(false) { }
17
     void prepare();
17
     void prepare();
18
+    void play();
19
+    void stop();
18
     glm::vec3 getPos() { return pos; }
20
     glm::vec3 getPos() { return pos; }
19
     int getID() { return id; }
21
     int getID() { return id; }
20
     int getFlags() { return flags; }
22
     int getFlags() { return flags; }
21
     int getSource() { return source; }
23
     int getSource() { return source; }
24
+    bool isPlaying() { return playing; }
22
 
25
 
23
   private:
26
   private:
24
     glm::vec3 pos;
27
     glm::vec3 pos;
25
     int id, flags, source;
28
     int id, flags, source;
29
+    bool playing;
26
 };
30
 };
27
 
31
 
28
 class SoundDetail {
32
 class SoundDetail {

+ 1
- 0
include/system/Sound.h View File

24
     static void listenAt(glm::vec3 pos, glm::vec3 at, glm::vec3 up);
24
     static void listenAt(glm::vec3 pos, glm::vec3 at, glm::vec3 up);
25
 
25
 
26
     static void play(int source, bool atListener = false);
26
     static void play(int source, bool atListener = false);
27
+    static void stop(int source);
27
     static void stopAll();
28
     static void stopAll();
28
 
29
 
29
     static void setEnabled(bool on = true);
30
     static void setEnabled(bool on = true);

+ 1
- 0
include/system/SoundAL.h View File

26
     static void listenAt(glm::vec3 pos, glm::vec3 at, glm::vec3 up);
26
     static void listenAt(glm::vec3 pos, glm::vec3 at, glm::vec3 up);
27
 
27
 
28
     static void play(int source, bool atListener);
28
     static void play(int source, bool atListener);
29
+    static void stop(int source);
29
     static void stopAll();
30
     static void stopAll();
30
 
31
 
31
     static void setEnabled(bool on);
32
     static void setEnabled(bool on);

+ 0
- 30
src/CMakeLists.txt View File

170
 
170
 
171
 #################################################################
171
 #################################################################
172
 
172
 
173
-# Check for SSE, enable if available
174
-include (../cmake/FindSSE.cmake)
175
-if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
176
-    if (SSE_FOUND)
177
-        set (SSE_FOUND_MSG "${SSE_FOUND_MSG} SSE")
178
-        set (OpenRaider_CXX_FLAGS "${OpenRaider_CXX_FLAGS} -msse")
179
-    endif (SSE_FOUND)
180
-    if (SSE2_FOUND)
181
-        set (SSE_FOUND_MSG "${SSE_FOUND_MSG} SSE2")
182
-        set (OpenRaider_CXX_FLAGS "${OpenRaider_CXX_FLAGS} -msse2")
183
-    endif (SSE2_FOUND)
184
-    if (SSE3_FOUND)
185
-        set (SSE_FOUND_MSG "${SSE_FOUND_MSG} SSE3")
186
-        set (OpenRaider_CXX_FLAGS "${OpenRaider_CXX_FLAGS} -msse3")
187
-    endif (SSE3_FOUND)
188
-    if (SSSE3_FOUND)
189
-        set (SSE_FOUND_MSG "${SSE_FOUND_MSG} SSSE3")
190
-        set (OpenRaider_CXX_FLAGS "${OpenRaider_CXX_FLAGS} -mssse3")
191
-    endif (SSSE3_FOUND)
192
-    if (SSE4_1_FOUND)
193
-        set (SSE_FOUND_MSG "${SSE_FOUND_MSG} SSE4.1")
194
-        set (OpenRaider_CXX_FLAGS "${OpenRaider_CXX_FLAGS} -msse4.1")
195
-    endif (SSE4_1_FOUND)
196
-
197
-    # Display message if something is enabled
198
-    if (NOT "${SSE_FOUND_MSG}" STREQUAL "")
199
-        message (STATUS "Enabled${SSE_FOUND_MSG}...")
200
-    endif (NOT "${SSE_FOUND_MSG}" STREQUAL "")
201
-endif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
202
-
203
 # Apply Flags
173
 # Apply Flags
204
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenRaider_CXX_FLAGS}")
174
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenRaider_CXX_FLAGS}")
205
 set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${OpenRaider_CXX_FLAGS} ${OpenRaider_CXX_FLAGS_DEBUG}")
175
 set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${OpenRaider_CXX_FLAGS} ${OpenRaider_CXX_FLAGS_DEBUG}")

+ 3
- 0
src/MenuFolder.cpp View File

119
             showDialog("Error reading subfolder!", "OK", "");
119
             showDialog("Error reading subfolder!", "OK", "");
120
         }
120
         }
121
     } else {
121
     } else {
122
+        showDialog("Loading...", "OK");
123
+        renderFrame();
122
         int error = Game::loadLevel(mapFolder->getFile((unsigned long)mCursor
124
         int error = Game::loadLevel(mapFolder->getFile((unsigned long)mCursor
123
                                     - 1 - mapFolder->folderCount()).getPath().c_str());
125
                                     - 1 - mapFolder->folderCount()).getPath().c_str());
126
+        ackDialog();
124
         if (error == 0) {
127
         if (error == 0) {
125
             visible = false;
128
             visible = false;
126
         } else {
129
         } else {

+ 92
- 9
src/SoundManager.cpp View File

32
             if (ret < 0) {
32
             if (ret < 0) {
33
                 Log::get(LOG_ERROR) << "Error positioning SoundSource " << id << Log::endl;
33
                 Log::get(LOG_ERROR) << "Error positioning SoundSource " << id << Log::endl;
34
             }
34
             }
35
-            Sound::play(source, false);
36
         }
35
         }
37
     }
36
     }
38
 }
37
 }
39
 
38
 
39
+void SoundSource::play() {
40
+    playing = true;
41
+
42
+    if (source >= 0)
43
+        Sound::play(source, false);
44
+}
45
+
46
+void SoundSource::stop() {
47
+    playing = false;
48
+
49
+    if (source >= 0)
50
+        Sound::stop(source);
51
+}
52
+
40
 // ----------------------------------------------------------------------------
53
 // ----------------------------------------------------------------------------
41
 
54
 
42
 std::vector<SoundSource> SoundManager::soundSources;
55
 std::vector<SoundSource> SoundManager::soundSources;
69
 
82
 
70
     for (int i = 0; i < soundSources.size(); i++) {
83
     for (int i = 0; i < soundSources.size(); i++) {
71
         soundSources.at(i).prepare();
84
         soundSources.at(i).prepare();
85
+        soundSources.at(i).play();
72
     }
86
     }
73
 
87
 
74
     return 0;
88
     return 0;
142
 }
156
 }
143
 
157
 
144
 void SoundManager::display() {
158
 void SoundManager::display() {
159
+    static bool offsets = false;
145
     if (ImGui::CollapsingHeader("Sound Sources")) {
160
     if (ImGui::CollapsingHeader("Sound Sources")) {
146
         ImGui::Columns(5, "soundsources");
161
         ImGui::Columns(5, "soundsources");
147
-        ImGui::Text("No"); ImGui::NextColumn();
148
-        ImGui::Text("ID"); ImGui::NextColumn();
149
-        ImGui::Text("Flags"); ImGui::NextColumn();
150
-        ImGui::Text("Pos"); ImGui::NextColumn();
151
-        ImGui::Text("Go"); ImGui::NextColumn();
162
+        ImGui::Text("No");
163
+        ImGui::NextColumn();
164
+        ImGui::Text("ID");
165
+        ImGui::NextColumn();
166
+        ImGui::Text("Flags");
167
+        ImGui::NextColumn();
168
+        ImGui::Text("Pos");
169
+        ImGui::NextColumn();
170
+        ImGui::Text("Tools");
171
+        ImGui::NextColumn();
152
         ImGui::Separator();
172
         ImGui::Separator();
173
+        if (!offsets) {
174
+            ImGui::SetColumnOffset(1, 40.0f);
175
+            ImGui::SetColumnOffset(2, 80.0f);
176
+            ImGui::SetColumnOffset(3, 130.0f);
177
+            ImGui::SetColumnOffset(4, 350.0f);
178
+            offsets = true;
179
+        }
153
         for (int i = 0; i < soundSources.size(); i++) {
180
         for (int i = 0; i < soundSources.size(); i++) {
154
             auto& ss = soundSources.at(i);
181
             auto& ss = soundSources.at(i);
155
             ImGui::Text("%03d", i);
182
             ImGui::Text("%03d", i);
156
             ImGui::NextColumn();
183
             ImGui::NextColumn();
157
             ImGui::Text("%d", ss.getID());
184
             ImGui::Text("%d", ss.getID());
158
             ImGui::NextColumn();
185
             ImGui::NextColumn();
159
-            ImGui::Text("%X", ss.getFlags());
186
+            ImGui::Text("0x%X", ss.getFlags());
160
             ImGui::NextColumn();
187
             ImGui::NextColumn();
161
             ImGui::Text("%.1f %.1f %.1f", ss.getPos().x, ss.getPos().y, ss.getPos().z);
188
             ImGui::Text("%.1f %.1f %.1f", ss.getPos().x, ss.getPos().y, ss.getPos().z);
162
             ImGui::NextColumn();
189
             ImGui::NextColumn();
163
             ImGui::PushID(i);
190
             ImGui::PushID(i);
164
-            if (ImGui::Button("Go!")) {
191
+            if (ImGui::Button("Warp")) {
165
                 Camera::setPosition(ss.getPos());
192
                 Camera::setPosition(ss.getPos());
166
             }
193
             }
194
+            ImGui::SameLine();
195
+            if (ImGui::Button("Play")) {
196
+                playSound(soundSources.at(i).getID());
197
+            }
198
+            ImGui::SameLine();
199
+            if (ss.isPlaying()) {
200
+                if (ImGui::Button("Stop")) {
201
+                    ss.stop();
202
+                }
203
+            } else {
204
+                if (ImGui::Button("Start")) {
205
+                    ss.play();
206
+                }
207
+            }
208
+            ImGui::PopID();
209
+            ImGui::NextColumn();
210
+        }
211
+        ImGui::Columns(1);
212
+    }
213
+
214
+    static bool offsets2 = false;
215
+    if (ImGui::CollapsingHeader("Sound Details")) {
216
+        ImGui::Columns(4, "sounddetails");
217
+        ImGui::Text("No");
218
+        ImGui::NextColumn();
219
+        ImGui::Text("Vol");
220
+        ImGui::NextColumn();
221
+        ImGui::Text("Sample");
222
+        ImGui::NextColumn();
223
+        ImGui::Text("Tools");
224
+        ImGui::NextColumn();
225
+        ImGui::Separator();
226
+        if (!offsets2) {
227
+            ImGui::SetColumnOffset(1, 40.0f);
228
+            ImGui::SetColumnOffset(2, 80.0f);
229
+            ImGui::SetColumnOffset(3, 180.0f);
230
+            offsets2 = true;
231
+        }
232
+        for (int i = 0; i < soundDetails.size(); i++) {
233
+            auto& sd = soundDetails.at(i);
234
+            ImGui::Text("%03d", i);
235
+            ImGui::NextColumn();
236
+            ImGui::Text("%.2f", sd.getVolume());
237
+            ImGui::NextColumn();
238
+            if ((sd.getSample() < 0) || (sd.getSample() >= sampleIndices.size())) {
239
+                ImGui::Text("%03d --> ???", sd.getSample());
240
+            } else {
241
+                ImGui::Text("%03d --> %03d", sd.getSample(), sampleIndices.at(sd.getSample()));
242
+            }
243
+            ImGui::NextColumn();
244
+            ImGui::PushID(i);
245
+            if (sd.getSource() >= 0) {
246
+                if (ImGui::Button("Play")) {
247
+                    Sound::play(sd.getSource(), true);
248
+                }
249
+            }
167
             ImGui::PopID();
250
             ImGui::PopID();
168
             ImGui::NextColumn();
251
             ImGui::NextColumn();
169
         }
252
         }
170
         ImGui::Columns(1);
253
         ImGui::Columns(1);
171
     }
254
     }
172
 
255
 
173
-    if (ImGui::CollapsingHeader("Sound Player")) {
256
+    if (ImGui::CollapsingHeader("Sound Map Player")) {
174
         if (!Sound::getEnabled()) {
257
         if (!Sound::getEnabled()) {
175
             ImGui::Text("Please enable Sound first!");
258
             ImGui::Text("Please enable Sound first!");
176
             if (ImGui::Button("Enable Sound!")) {
259
             if (ImGui::Button("Enable Sound!")) {

+ 2
- 2
src/UI.cpp View File

139
     style.ItemInnerSpacing                      = ImVec2(1, 1);
139
     style.ItemInnerSpacing                      = ImVec2(1, 1);
140
     style.TouchExtraPadding                     = ImVec2(0, 0);
140
     style.TouchExtraPadding                     = ImVec2(0, 0);
141
     style.TreeNodeSpacing                       = 3;
141
     style.TreeNodeSpacing                       = 3;
142
-    style.ScrollBarWidth                        = 10;
142
+    style.ScrollbarWidth                        = 10;
143
 
143
 
144
     return 0;
144
     return 0;
145
 }
145
 }
274
 
274
 
275
     static bool showTestWindow = false;
275
     static bool showTestWindow = false;
276
     static bool showStyleWindow = false;
276
     static bool showStyleWindow = false;
277
-    if (ImGui::Begin("Engine", &visible, ImVec2(400, 400))) {
277
+    if (ImGui::Begin("Engine", &visible, ImVec2(500, 600))) {
278
         Render::displayUI();
278
         Render::displayUI();
279
         RunTime::display();
279
         RunTime::display();
280
         TextureManager::display();
280
         TextureManager::display();

+ 267
- 142
src/deps/imgui/imgui.cpp View File

1
-// ImGui library v1.35 wip
1
+// ImGui library v1.35
2
 // See ImGui::ShowTestWindow() for sample code.
2
 // See ImGui::ShowTestWindow() for sample code.
3
 // Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
3
 // Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
4
 // Get latest version at https://github.com/ocornut/imgui
4
 // Get latest version at https://github.com/ocornut/imgui
129
  Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
129
  Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
130
  Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
130
  Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
131
  
131
  
132
+ - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth
132
  - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond), kept inline redirection function.
133
  - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond), kept inline redirection function.
133
  - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
134
  - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
134
  - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
135
  - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
262
  - main: IsItemHovered() returns true even if mouse is active on another widget (e.g. dragging outside of sliders). Maybe not a sensible default? Add parameter or alternate function?
263
  - main: IsItemHovered() returns true even if mouse is active on another widget (e.g. dragging outside of sliders). Maybe not a sensible default? Add parameter or alternate function?
263
  - main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
264
  - main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
264
  - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
265
  - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
265
- - scrollbar: use relative mouse movement when first-clicking inside of scroll grab box.
266
- - scrollbar: make the grab visible and a minimum size for long scroll regions
267
 !- input number: very large int not reliably supported because of int<>float conversions.
266
 !- input number: very large int not reliably supported because of int<>float conversions.
268
  - input number: optional range min/max for Input*() functions
267
  - input number: optional range min/max for Input*() functions
269
  - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
268
  - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
290
  - plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID)
289
  - plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID)
291
  - file selection widget -> build the tool in our codebase to improve model-dialog idioms
290
  - file selection widget -> build the tool in our codebase to improve model-dialog idioms
292
  - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
291
  - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
293
- - slider: initial absolute click is imprecise. change to relative movement slider? hide mouse cursor, allow more precise input using less screen-space.
292
+ - slider: initial absolute click is imprecise. change to relative movement slider? hide mouse cursor, allow more precise input using less screen-space. same as scrollbar.
294
  - text edit: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now.
293
  - text edit: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now.
295
  - text edit: centered text for slider as input text so it matches typical positioning.
294
  - text edit: centered text for slider as input text so it matches typical positioning.
296
  - text edit: flag to disable live update of the user buffer. 
295
  - text edit: flag to disable live update of the user buffer. 
393
 #endif
392
 #endif
394
 #include "stb_truetype.h"
393
 #include "stb_truetype.h"
395
 
394
 
396
-#define STB_TEXTEDIT_STRING ImGuiTextEditState
397
-#define STB_TEXTEDIT_CHARTYPE ImWchar
395
+#define STB_TEXTEDIT_STRING    ImGuiTextEditState
396
+#define STB_TEXTEDIT_CHARTYPE  ImWchar
398
 #include "stb_textedit.h"
397
 #include "stb_textedit.h"
399
 
398
 
400
 #ifdef __clang__
399
 #ifdef __clang__
410
 // Forward Declarations
409
 // Forward Declarations
411
 //-------------------------------------------------------------------------
410
 //-------------------------------------------------------------------------
412
 
411
 
412
+struct ImGuiColMod;
413
+struct ImGuiStyleMod;
413
 struct ImGuiAabb;
414
 struct ImGuiAabb;
415
+struct ImGuiDrawContext;
416
+struct ImGuiTextEditState;
417
+struct ImGuiIniData;
418
+struct ImGuiState;
419
+struct ImGuiWindow;
414
 
420
 
415
 static bool         ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat = false, bool pressed_on_click = false);
421
 static bool         ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat = false, bool pressed_on_click = false);
416
 static void         LogText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL);
422
 static void         LogText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL);
431
 static bool         IsMouseHoveringBox(const ImGuiAabb& bb);
437
 static bool         IsMouseHoveringBox(const ImGuiAabb& bb);
432
 static bool         IsKeyPressedMap(ImGuiKey key, bool repeat = true);
438
 static bool         IsKeyPressedMap(ImGuiKey key, bool repeat = true);
433
 
439
 
440
+static void         Scrollbar(ImGuiWindow* window);
434
 static bool         CloseWindowButton(bool* p_opened = NULL);
441
 static bool         CloseWindowButton(bool* p_opened = NULL);
435
 static void         FocusWindow(ImGuiWindow* window);
442
 static void         FocusWindow(ImGuiWindow* window);
436
 static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs);
443
 static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs);
454
 static int          ImTextCharToUtf8(char* buf, size_t buf_size, unsigned int in_char);                                // return output UTF-8 bytes count
461
 static int          ImTextCharToUtf8(char* buf, size_t buf_size, unsigned int in_char);                                // return output UTF-8 bytes count
455
 static ptrdiff_t    ImTextStrToUtf8(char* buf, size_t buf_size, const ImWchar* in_text, const ImWchar* in_text_end);   // return output UTF-8 bytes count
462
 static ptrdiff_t    ImTextStrToUtf8(char* buf, size_t buf_size, const ImWchar* in_text, const ImWchar* in_text_end);   // return output UTF-8 bytes count
456
 static int          ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end);          // return input UTF-8 bytes count
463
 static int          ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end);          // return input UTF-8 bytes count
457
-static ptrdiff_t    ImTextStrFromUtf8(ImWchar* buf, size_t buf_size, const char* in_text, const char* in_text_end);    // return input UTF-8 bytes count
464
+static ptrdiff_t    ImTextStrFromUtf8(ImWchar* buf, size_t buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL);   // return input UTF-8 bytes count
458
 static int          ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end);                            // return number of UTF-8 code-points (NOT bytes count)
465
 static int          ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end);                            // return number of UTF-8 code-points (NOT bytes count)
459
-static int          ImTextCountUtf8BytesFromWchar(const ImWchar* in_text, const ImWchar* in_text_end);                 // return number of bytes to express string as UTF-8 code-points
466
+static int          ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end);                   // return number of bytes to express string as UTF-8 code-points
460
 
467
 
461
 //-----------------------------------------------------------------------------
468
 //-----------------------------------------------------------------------------
462
 // Platform dependent default implementations
469
 // Platform dependent default implementations
497
     WindowFillAlphaDefault  = 0.70f;            // Default alpha of window background, if not specified in ImGui::Begin()
504
     WindowFillAlphaDefault  = 0.70f;            // Default alpha of window background, if not specified in ImGui::Begin()
498
     TreeNodeSpacing         = 22.0f;            // Horizontal spacing when entering a tree node
505
     TreeNodeSpacing         = 22.0f;            // Horizontal spacing when entering a tree node
499
     ColumnsMinSpacing       = 6.0f;             // Minimum horizontal spacing between two columns
506
     ColumnsMinSpacing       = 6.0f;             // Minimum horizontal spacing between two columns
500
-    ScrollBarWidth          = 16.0f;            // Width of the vertical scroll bar
507
+    ScrollbarWidth          = 16.0f;            // Width of the vertical scrollbar
508
+    GrabMinSize             = 10.0f;            // Minimum width/height of a slider or scrollbar grab
501
 
509
 
502
     Colors[ImGuiCol_Text]                   = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
510
     Colors[ImGuiCol_Text]                   = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
503
     Colors[ImGuiCol_WindowBg]               = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
511
     Colors[ImGuiCol_WindowBg]               = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
948
 {
956
 {
949
     ImGuiID             Id;                             // widget id owning the text state
957
     ImGuiID             Id;                             // widget id owning the text state
950
     ImWchar             Text[1024];                     // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
958
     ImWchar             Text[1024];                     // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
951
-    char                InitialText[1024*3+1];          // backup of end-user buffer at the time of focus (in UTF-8, unconverted)
952
-    size_t              BufSize;                        // end-user buffer size, <= 1024 (or increase above)
959
+    char                InitialText[1024*4+1];          // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
960
+    size_t              CurLenA, CurLenW;               // we need to maintain our buffer length in both UTF-8 and wchar format.
961
+    size_t              BufSizeA;                       // end-user buffer size, <= 1024 (or increase above)
953
     float               Width;                          // widget width
962
     float               Width;                          // widget width
954
     float               ScrollX;
963
     float               ScrollX;
955
     STB_TexteditState   StbState;
964
     STB_TexteditState   StbState;
1039
     ImGuiID                 SliderAsInputTextId;
1048
     ImGuiID                 SliderAsInputTextId;
1040
     ImGuiStorage            ColorEditModeStorage;               // for user selection
1049
     ImGuiStorage            ColorEditModeStorage;               // for user selection
1041
     ImGuiID                 ActiveComboID;
1050
     ImGuiID                 ActiveComboID;
1051
+    float                   ScrollbarClickDeltaToGrabCenter;    // distance between mouse and center of grab box, normalized in parent space
1042
     char                    Tooltip[1024];
1052
     char                    Tooltip[1024];
1043
     char*                   PrivateClipboard;                   // if no custom clipboard handler is defined
1053
     char*                   PrivateClipboard;                   // if no custom clipboard handler is defined
1044
 
1054
 
1088
 
1098
 
1089
         SliderAsInputTextId = 0;
1099
         SliderAsInputTextId = 0;
1090
         ActiveComboID = 0;
1100
         ActiveComboID = 0;
1101
+        ScrollbarClickDeltaToGrabCenter = 0.0f;
1091
         memset(Tooltip, 0, sizeof(Tooltip));
1102
         memset(Tooltip, 0, sizeof(Tooltip));
1092
         PrivateClipboard = NULL;
1103
         PrivateClipboard = NULL;
1093
 
1104
 
1115
     ImVec2                  Pos;                                // Position rounded-up to nearest pixel
1126
     ImVec2                  Pos;                                // Position rounded-up to nearest pixel
1116
     ImVec2                  Size;                               // Current size (==SizeFull or collapsed title bar size)
1127
     ImVec2                  Size;                               // Current size (==SizeFull or collapsed title bar size)
1117
     ImVec2                  SizeFull;                           // Size when non collapsed
1128
     ImVec2                  SizeFull;                           // Size when non collapsed
1118
-    ImVec2                  SizeContentsFit;                    // Size of contents (extents reach by the drawing cursor) - may not fit within Size.
1129
+    ImVec2                  SizeContents;                       // Size of contents (== extents reach of the drawing cursor) from previous frame
1130
+    ImVec2                  SizeContentsCurrent;                // Size of contents, currently extending
1119
     float                   ScrollY;
1131
     float                   ScrollY;
1120
     float                   NextScrollY;
1132
     float                   NextScrollY;
1121
     bool                    ScrollbarY;
1133
     bool                    ScrollbarY;
1457
     Flags = 0;
1469
     Flags = 0;
1458
     PosFloat = Pos = ImVec2(0.0f, 0.0f);
1470
     PosFloat = Pos = ImVec2(0.0f, 0.0f);
1459
     Size = SizeFull = ImVec2(0.0f, 0.0f);
1471
     Size = SizeFull = ImVec2(0.0f, 0.0f);
1460
-    SizeContentsFit = ImVec2(0.0f, 0.0f);
1472
+    SizeContents = SizeContentsCurrent = ImVec2(0.0f, 0.0f);
1461
     ScrollY = 0.0f;
1473
     ScrollY = 0.0f;
1462
     NextScrollY = 0.0f;
1474
     NextScrollY = 0.0f;
1463
     ScrollbarY = false;
1475
     ScrollbarY = false;
1823
     // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application.
1835
     // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application.
1824
     // When clicking outside of a window we assume the click is owned by the application and won't request capture.
1836
     // When clicking outside of a window we assume the click is owned by the application and won't request capture.
1825
     int mouse_earliest_button_down = -1;
1837
     int mouse_earliest_button_down = -1;
1826
-    for (size_t i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
1838
+    for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
1827
     {
1839
     {
1828
         if (g.IO.MouseClicked[i])
1840
         if (g.IO.MouseClicked[i])
1829
             g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL);
1841
             g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL);
2795
         window->LastFrameDrawn = current_frame;
2807
         window->LastFrameDrawn = current_frame;
2796
         window->ClipRectStack.resize(0);
2808
         window->ClipRectStack.resize(0);
2797
 
2809
 
2810
+        // Reset contents size for auto-fitting
2811
+        window->SizeContents = window->SizeContentsCurrent;
2812
+        window->SizeContentsCurrent = ImVec2(0.0f, 0.0f);
2813
+
2798
         if (flags & ImGuiWindowFlags_ChildWindow)
2814
         if (flags & ImGuiWindowFlags_ChildWindow)
2799
         {
2815
         {
2800
             parent_window->DC.ChildWindows.push_back(window);
2816
             parent_window->DC.ChildWindows.push_back(window);
2889
         window->ScrollY = window->NextScrollY;
2905
         window->ScrollY = window->NextScrollY;
2890
         window->ScrollY = ImMax(window->ScrollY, 0.0f);
2906
         window->ScrollY = ImMax(window->ScrollY, 0.0f);
2891
         if (!window->Collapsed && !window->SkipItems)
2907
         if (!window->Collapsed && !window->SkipItems)
2892
-            window->ScrollY = ImMin(window->ScrollY, ImMax(0.0f, (float)window->SizeContentsFit.y - window->SizeFull.y));
2908
+            window->ScrollY = ImMin(window->ScrollY, ImMax(0.0f, window->SizeContents.y - window->SizeFull.y));
2893
         window->NextScrollY = window->ScrollY;
2909
         window->NextScrollY = window->ScrollY;
2894
 
2910
 
2895
         // At this point we don't have a clipping rectangle setup yet, so we can test and draw in title bar
2911
         // At this point we don't have a clipping rectangle setup yet, so we can test and draw in title bar
2929
             if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0)
2945
             if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0)
2930
             {
2946
             {
2931
                 // Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose.
2947
                 // Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose.
2932
-                const ImVec2 size_auto_fit = window->SizeContentsFit + style.WindowPadding - ImVec2(0.0f, style.ItemSpacing.y);
2948
+                const ImVec2 size_auto_fit = window->SizeContents + style.WindowPadding - ImVec2(0.0f, style.ItemSpacing.y);
2933
                 window->SizeFull = size_auto_fit;
2949
                 window->SizeFull = size_auto_fit;
2934
             }
2950
             }
2935
             else
2951
             else
2936
             {
2952
             {
2937
-                const ImVec2 size_auto_fit = ImClamp(window->SizeContentsFit + style.AutoFitPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.AutoFitPadding));
2953
+                const ImVec2 size_auto_fit = ImClamp(window->SizeContents + style.AutoFitPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.AutoFitPadding));
2938
                 if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
2954
                 if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
2939
                 {
2955
                 {
2940
                     // Don't continuously mark settings as dirty, the size of the window doesn't need to be stored.
2956
                     // Don't continuously mark settings as dirty, the size of the window doesn't need to be stored.
2982
             }
2998
             }
2983
 
2999
 
2984
             // Scrollbar
3000
             // Scrollbar
2985
-            window->ScrollbarY = (window->SizeContentsFit.y > window->Size.y) && !(window->Flags & ImGuiWindowFlags_NoScrollbar);
3001
+            window->ScrollbarY = (window->SizeContents.y > window->Size.y) && !(window->Flags & ImGuiWindowFlags_NoScrollbar);
2986
 
3002
 
2987
             // Window background
3003
             // Window background
2988
             if (bg_alpha > 0.0f)
3004
             if (bg_alpha > 0.0f)
2992
                 else if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0)
3008
                 else if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0)
2993
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_TooltipBg, bg_alpha), window_rounding);
3009
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_TooltipBg, bg_alpha), window_rounding);
2994
                 else if ((window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
3010
                 else if ((window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
2995
-                    window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size-ImVec2(window->ScrollbarY?style.ScrollBarWidth:0.0f,0.0f), window->Color(ImGuiCol_ChildWindowBg, bg_alpha), window_rounding, window->ScrollbarY ? (1|8) : (0xF));
3011
+                    window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size-ImVec2(window->ScrollbarY?style.ScrollbarWidth:0.0f,0.0f), window->Color(ImGuiCol_ChildWindowBg, bg_alpha), window_rounding, window->ScrollbarY ? (1|8) : (0xF));
2996
                 else
3012
                 else
2997
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_WindowBg, bg_alpha), window_rounding);
3013
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_WindowBg, bg_alpha), window_rounding);
2998
             }
3014
             }
3012
 
3028
 
3013
             // Scrollbar
3029
             // Scrollbar
3014
             if (window->ScrollbarY)
3030
             if (window->ScrollbarY)
3015
-            {
3016
-                ImGuiAabb scrollbar_bb(window->Aabb().Max.x - style.ScrollBarWidth, title_bar_aabb.Max.y+1, window->Aabb().Max.x, window->Aabb().Max.y-1);
3017
-                //window->DrawList->AddLine(scrollbar_bb.GetTL(), scrollbar_bb.GetBL(), g.Colors[ImGuiCol_Border]);
3018
-                window->DrawList->AddRectFilled(scrollbar_bb.Min, scrollbar_bb.Max, window->Color(ImGuiCol_ScrollbarBg));
3019
-                scrollbar_bb.Expand(ImVec2(-3,-3));
3020
-
3021
-                const float grab_size_y_norm = ImSaturate(window->Size.y / ImMax(window->SizeContentsFit.y, window->Size.y));
3022
-                const float grab_size_y = scrollbar_bb.GetHeight() * grab_size_y_norm;
3023
-
3024
-                // Handle input right away (none of the code above is relying on scrolling position)
3025
-                bool held = false;
3026
-                bool hovered = false;
3027
-                if (grab_size_y_norm < 1.0f)
3028
-                {
3029
-                    const ImGuiID scrollbar_id = window->GetID("#SCROLLY");
3030
-                    ButtonBehaviour(scrollbar_bb, scrollbar_id, &hovered, &held, true);
3031
-                    if (held)
3032
-                    {
3033
-                        g.HoveredId = scrollbar_id;
3034
-                        const float pos_y_norm = ImSaturate((g.IO.MousePos.y - (scrollbar_bb.Min.y + grab_size_y*0.5f)) / (scrollbar_bb.GetHeight() - grab_size_y)) * (1.0f - grab_size_y_norm);
3035
-                        window->ScrollY = (float)(int)(pos_y_norm * window->SizeContentsFit.y);
3036
-                        window->NextScrollY = window->ScrollY;
3037
-                    }
3038
-                }
3039
-
3040
-                // Normalized height of the grab
3041
-                const float pos_y_norm = ImSaturate(window->ScrollY / ImMax(0.0f, window->SizeContentsFit.y));
3042
-                const ImU32 grab_col = window->Color(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab);
3043
-                window->DrawList->AddRectFilled(
3044
-                    ImVec2(scrollbar_bb.Min.x, ImLerp(scrollbar_bb.Min.y, scrollbar_bb.Max.y, pos_y_norm)), 
3045
-                    ImVec2(scrollbar_bb.Max.x, ImLerp(scrollbar_bb.Min.y, scrollbar_bb.Max.y, pos_y_norm + grab_size_y_norm)), grab_col);
3046
-            }
3031
+                Scrollbar(window);
3047
 
3032
 
3048
             // Render resize grip
3033
             // Render resize grip
3049
             // (after the input handling so we don't have a frame of latency)
3034
             // (after the input handling so we don't have a frame of latency)
3088
         window->DC.TreeDepth = 0;
3073
         window->DC.TreeDepth = 0;
3089
         window->DC.StateStorage = &window->StateStorage;
3074
         window->DC.StateStorage = &window->StateStorage;
3090
 
3075
 
3091
-        // Reset contents size for auto-fitting
3092
-        window->SizeContentsFit = ImVec2(0.0f, 0.0f);
3093
         if (window->AutoFitFrames > 0)
3076
         if (window->AutoFitFrames > 0)
3094
             window->AutoFitFrames--;
3077
             window->AutoFitFrames--;
3095
 
3078
 
3121
     const ImGuiAabb title_bar_aabb = window->TitleBarAabb();
3104
     const ImGuiAabb title_bar_aabb = window->TitleBarAabb();
3122
     ImVec4 clip_rect(title_bar_aabb.Min.x+0.5f+window->WindowPadding().x*0.5f, title_bar_aabb.Max.y+0.5f, window->Aabb().Max.x+0.5f-window->WindowPadding().x*0.5f, window->Aabb().Max.y-1.5f);
3105
     ImVec4 clip_rect(title_bar_aabb.Min.x+0.5f+window->WindowPadding().x*0.5f, title_bar_aabb.Max.y+0.5f, window->Aabb().Max.x+0.5f-window->WindowPadding().x*0.5f, window->Aabb().Max.y-1.5f);
3123
     if (window->ScrollbarY)
3106
     if (window->ScrollbarY)
3124
-        clip_rect.z -= style.ScrollBarWidth;
3107
+        clip_rect.z -= style.ScrollbarWidth;
3125
     PushClipRect(clip_rect);
3108
     PushClipRect(clip_rect);
3126
 
3109
 
3127
     // Clear 'accessed' flag last thing
3110
     // Clear 'accessed' flag last thing
3171
     g.CurrentWindow = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back();
3154
     g.CurrentWindow = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back();
3172
 }
3155
 }
3173
 
3156
 
3157
+// Vertical scrollbar
3158
+// The entire piece of code below is rather confusing because:
3159
+// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab)
3160
+// - We store values as ratio and in a form that allows the window content to change while we are holding on a scrollbar
3161
+static void Scrollbar(ImGuiWindow* window)
3162
+{
3163
+    ImGuiState& g = *GImGui;
3164
+    const ImGuiStyle& style = g.Style;
3165
+    const ImGuiID id = window->GetID("#SCROLLY");
3166
+
3167
+    // Render background
3168
+    ImGuiAabb bb(window->Aabb().Max.x - style.ScrollbarWidth, window->Pos.y + window->TitleBarHeight()+1, window->Aabb().Max.x, window->Aabb().Max.y-1);
3169
+    window->DrawList->AddRectFilled(bb.Min, bb.Max, window->Color(ImGuiCol_ScrollbarBg));
3170
+    bb.Expand(ImVec2(-3,-3));
3171
+    const float scrollbar_height = bb.GetHeight();
3172
+
3173
+    // The grabable box size generally represent the amount visible (vs the total scrollable amount)
3174
+    // But we maintain a minimum size in pixel to allow for the user to still aim inside.
3175
+    const float grab_h_pixels = ImMax(style.GrabMinSize, scrollbar_height * ImSaturate(window->Size.y / ImMax(window->SizeContents.y, window->Size.y)));
3176
+    const float grab_h_norm = grab_h_pixels / scrollbar_height;
3177
+
3178
+    // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
3179
+    bool held = false;
3180
+    bool hovered = false;
3181
+    const bool previously_held = (g.ActiveId == id);
3182
+    ButtonBehaviour(bb, id, &hovered, &held, true);
3183
+
3184
+    const float scroll_max = ImMax(1.0f, window->SizeContents.y - window->Size.y);
3185
+    float scroll_ratio = ImSaturate(window->ScrollY / scroll_max);
3186
+    float grab_y_norm = scroll_ratio * (scrollbar_height - grab_h_pixels) / scrollbar_height;
3187
+    if (held)
3188
+    {
3189
+        const float clicked_y_norm = ImSaturate((g.IO.MousePos.y - bb.Min.y) / scrollbar_height);     // Click position in scrollbar space (0.0f->1.0f)
3190
+        g.HoveredId = id;
3191
+
3192
+        bool seek_absolute = false;
3193
+        if (!previously_held)
3194
+        {
3195
+            // On initial click calculate the distance between mouse and the center of the grab
3196
+            if (clicked_y_norm >= grab_y_norm && clicked_y_norm <= grab_y_norm + grab_h_norm)
3197
+            {
3198
+                g.ScrollbarClickDeltaToGrabCenter = clicked_y_norm - grab_y_norm - grab_h_norm*0.5f;
3199
+            }
3200
+            else
3201
+            {
3202
+                seek_absolute = true;
3203
+                g.ScrollbarClickDeltaToGrabCenter = 0;
3204
+            }
3205
+        }
3206
+
3207
+        // Apply scroll
3208
+        const float scroll_y_norm = ImSaturate((clicked_y_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm*0.5f) / (1.0f - grab_h_norm));
3209
+        window->ScrollY = (float)(int)(0.5f + scroll_y_norm * (window->SizeContents.y - window->Size.y));
3210
+        window->NextScrollY = window->ScrollY;
3211
+
3212
+        // Update values for rendering
3213
+        scroll_ratio = ImSaturate(window->ScrollY / scroll_max);
3214
+        grab_y_norm = scroll_ratio * (scrollbar_height - grab_h_pixels) / scrollbar_height;
3215
+
3216
+        // Update distance to grab now that we have seeked and saturated
3217
+        if (seek_absolute)
3218
+            g.ScrollbarClickDeltaToGrabCenter = clicked_y_norm - grab_y_norm - grab_h_norm*0.5f;
3219
+    }
3220
+
3221
+    // Render
3222
+    const ImU32 grab_col = window->Color(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab);
3223
+    window->DrawList->AddRectFilled(ImVec2(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_y_norm)), ImVec2(bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_y_norm) + grab_h_pixels), grab_col);
3224
+}
3225
+
3174
 // Moving window to front of display (which happens to be back of our sorted list)
3226
 // Moving window to front of display (which happens to be back of our sorted list)
3175
 static void FocusWindow(ImGuiWindow* window)
3227
 static void FocusWindow(ImGuiWindow* window)
3176
 {
3228
 {
3591
     else
3643
     else
3592
     {
3644
     {
3593
         if (window->ScrollbarY)
3645
         if (window->ScrollbarY)
3594
-            mx.x -= GImGui->Style.ScrollBarWidth;
3646
+            mx.x -= GImGui->Style.ScrollbarWidth;
3595
     }
3647
     }
3596
     return mx;
3648
     return mx;
3597
 }
3649
 }
3607
     ImGuiWindow* window = GetCurrentWindow();
3659
     ImGuiWindow* window = GetCurrentWindow();
3608
     ImVec2 m = window->Size - window->WindowPadding();
3660
     ImVec2 m = window->Size - window->WindowPadding();
3609
     if (window->ScrollbarY)
3661
     if (window->ScrollbarY)
3610
-        m.x -= GImGui->Style.ScrollBarWidth;
3662
+        m.x -= GImGui->Style.ScrollbarWidth;
3611
     return m;
3663
     return m;
3612
 }
3664
 }
3613
 
3665
 
3670
 {
3722
 {
3671
     ImGuiWindow* window = GetCurrentWindow();
3723
     ImGuiWindow* window = GetCurrentWindow();
3672
     window->DC.CursorPos = window->Pos + pos;
3724
     window->DC.CursorPos = window->Pos + pos;
3673
-    window->SizeContentsFit = ImMax(window->SizeContentsFit, pos + ImVec2(0.0f, window->ScrollY));
3725
+    window->SizeContentsCurrent = ImMax(window->SizeContentsCurrent, pos + ImVec2(0.0f, window->ScrollY));
3674
 }
3726
 }
3675
 
3727
 
3676
 void ImGui::SetCursorPosX(float x)
3728
 void ImGui::SetCursorPosX(float x)
3677
 {
3729
 {
3678
     ImGuiWindow* window = GetCurrentWindow();
3730
     ImGuiWindow* window = GetCurrentWindow();
3679
     window->DC.CursorPos.x = window->Pos.x + x;
3731
     window->DC.CursorPos.x = window->Pos.x + x;
3680
-    window->SizeContentsFit.x = ImMax(window->SizeContentsFit.x, x);
3732
+    window->SizeContentsCurrent.x = ImMax(window->SizeContentsCurrent.x, x);
3681
 }
3733
 }
3682
 
3734
 
3683
 void ImGui::SetCursorPosY(float y)
3735
 void ImGui::SetCursorPosY(float y)
3684
 {
3736
 {
3685
     ImGuiWindow* window = GetCurrentWindow();
3737
     ImGuiWindow* window = GetCurrentWindow();
3686
     window->DC.CursorPos.y = window->Pos.y + y;
3738
     window->DC.CursorPos.y = window->Pos.y + y;
3687
-    window->SizeContentsFit.y = ImMax(window->SizeContentsFit.y, y + window->ScrollY);
3739
+    window->SizeContentsCurrent.y = ImMax(window->SizeContentsCurrent.y, y + window->ScrollY);
3688
 }
3740
 }
3689
 
3741
 
3690
 ImVec2 ImGui::GetCursorScreenPos()
3742
 ImVec2 ImGui::GetCursorScreenPos()
3699
     window->DC.CursorPos = screen_pos;
3751
     window->DC.CursorPos = screen_pos;
3700
 }
3752
 }
3701
 
3753
 
3754
+float ImGui::GetScrollPosY()
3755
+{
3756
+    ImGuiWindow* window = GetCurrentWindow();
3757
+    return window->ScrollY;
3758
+}
3759
+
3760
+float ImGui::GetScrollMaxY()
3761
+{
3762
+    ImGuiWindow* window = GetCurrentWindow();
3763
+    return window->SizeContents.y - window->SizeFull.y;
3764
+}
3765
+
3702
 void ImGui::SetScrollPosHere()
3766
 void ImGui::SetScrollPosHere()
3703
 {
3767
 {
3704
     ImGuiWindow* window = GetCurrentWindow();
3768
     ImGuiWindow* window = GetCurrentWindow();
4635
     const float grab_size_in_units = 1.0f;                                                              // In 'v' units. Probably needs to be parametrized, based on a 'v_step' value? decimal precision?
4699
     const float grab_size_in_units = 1.0f;                                                              // In 'v' units. Probably needs to be parametrized, based on a 'v_step' value? decimal precision?
4636
     float grab_size_in_pixels;
4700
     float grab_size_in_pixels;
4637
     if (decimal_precision > 0 || is_unbound)
4701
     if (decimal_precision > 0 || is_unbound)
4638
-        grab_size_in_pixels = 10.0f;
4702
+        grab_size_in_pixels = style.GrabMinSize;
4639
     else
4703
     else
4640
-        grab_size_in_pixels = ImMax(grab_size_in_units * (w / (v_max-v_min+1.0f)), 8.0f);               // Integer sliders
4704
+        grab_size_in_pixels = ImMax(grab_size_in_units * (w / (v_max-v_min+1.0f)), style.GrabMinSize);  // Integer sliders
4641
     const float slider_effective_w = slider_bb.GetWidth() - grab_size_in_pixels;
4705
     const float slider_effective_w = slider_bb.GetWidth() - grab_size_in_pixels;
4642
     const float slider_effective_x1 = slider_bb.Min.x + grab_size_in_pixels*0.5f;
4706
     const float slider_effective_x1 = slider_bb.Min.x + grab_size_in_pixels*0.5f;
4643
     const float slider_effective_x2 = slider_bb.Max.x - grab_size_in_pixels*0.5f;
4707
     const float slider_effective_x2 = slider_bb.Max.x - grab_size_in_pixels*0.5f;
5205
 
5269
 
5206
 static bool is_separator(unsigned int c)                                                          { return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
5270
 static bool is_separator(unsigned int c)                                                          { return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
5207
 #define STB_TEXTEDIT_IS_SPACE(CH)                                                                 ( ImCharIsSpace((unsigned int)CH) || is_separator((unsigned int)CH) )
5271
 #define STB_TEXTEDIT_IS_SPACE(CH)                                                                 ( ImCharIsSpace((unsigned int)CH) || is_separator((unsigned int)CH) )
5208
-static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)                    { ImWchar* dst = obj->Text+pos; const ImWchar* src = obj->Text+pos+n; while (ImWchar c = *src++) *dst++ = c; *dst = '\0'; }
5272
+static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)
5273
+{
5274
+    ImWchar* dst = obj->Text + pos;
5275
+
5276
+    // We maintain our buffer length in both UTF-8 and wchar formats
5277
+    obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);
5278
+    obj->CurLenW -= n;
5279
+
5280
+    // Offset remaining text
5281
+    const ImWchar* src = obj->Text + pos + n; 
5282
+    while (ImWchar c = *src++)
5283
+        *dst++ = c; 
5284
+    *dst = '\0';
5285
+}
5286
+
5209
 static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len)
5287
 static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len)
5210
 {
5288
 {
5211
-    const size_t text_len = ImStrlenW(obj->Text);
5212
-    if ((size_t)new_text_len + text_len + 1 > obj->BufSize)
5289
+    const size_t text_len = obj->CurLenW;
5290
+    if ((size_t)new_text_len + text_len + 1 > IM_ARRAYSIZE(obj->Text))
5291
+        return false;
5292
+
5293
+    const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
5294
+    if ((size_t)new_text_len_utf8 + obj->CurLenA + 1 > obj->BufSizeA)
5213
         return false;
5295
         return false;
5214
 
5296
 
5215
     if (pos != (int)text_len)
5297
     if (pos != (int)text_len)
5216
         memmove(obj->Text + (size_t)pos + new_text_len, obj->Text + (size_t)pos, (text_len - (size_t)pos) * sizeof(ImWchar));
5298
         memmove(obj->Text + (size_t)pos + new_text_len, obj->Text + (size_t)pos, (text_len - (size_t)pos) * sizeof(ImWchar));
5217
     memcpy(obj->Text + (size_t)pos, new_text, (size_t)new_text_len * sizeof(ImWchar));
5299
     memcpy(obj->Text + (size_t)pos, new_text, (size_t)new_text_len * sizeof(ImWchar));
5218
-    obj->Text[text_len + (size_t)new_text_len] = '\0';
5300
+
5301
+    obj->CurLenW += new_text_len;
5302
+    obj->CurLenA += new_text_len_utf8;
5303
+    obj->Text[obj->CurLenW] = '\0';
5219
 
5304
 
5220
     return true;
5305
     return true;
5221
 }
5306
 }
5310
     const char* text_start = GetTextPointerClippedA(font, font_size, buf, scroll_x, NULL);
5395
     const char* text_start = GetTextPointerClippedA(font, font_size, buf, scroll_x, NULL);
5311
     const char* text_end = GetTextPointerClippedA(font, font_size, text_start, width, &text_size);
5396
     const char* text_end = GetTextPointerClippedA(font, font_size, text_start, width, &text_size);
5312
 
5397
 
5398
+    // We need to test for the possibility of malformed UTF-8 (instead of just text_end[0] != 0)
5399
+    unsigned int text_end_char = 0;
5400
+    ImTextCharFromUtf8(&text_end_char, text_end, NULL);
5401
+
5313
     // Draw a little clip symbol if we've got text on either left or right of the box
5402
     // Draw a little clip symbol if we've got text on either left or right of the box
5314
     const char symbol_c = '~';
5403
     const char symbol_c = '~';
5315
     const float symbol_w = font_size*0.40f;     // FIXME: compute correct width
5404
     const float symbol_w = font_size*0.40f;     // FIXME: compute correct width
5316
     const float clip_begin = (text_start > buf && text_start < text_end) ? symbol_w : 0.0f;
5405
     const float clip_begin = (text_start > buf && text_start < text_end) ? symbol_w : 0.0f;
5317
-    const float clip_end = (text_end[0] != '\0' && text_end > text_start) ? symbol_w : 0.0f;
5406
+    const float clip_end = (text_end_char != 0 && text_end > text_start) ? symbol_w : 0.0f;
5318
 
5407
 
5319
     // Draw text
5408
     // Draw text
5320
     RenderText(pos+ImVec2(clip_begin,0), text_start+(clip_begin>0.0f?1:0), text_end-(clip_end>0.0f?1:0), false);
5409
     RenderText(pos+ImVec2(clip_begin,0), text_start+(clip_begin>0.0f?1:0), text_end-(clip_end>0.0f?1:0), false);
5459
 
5548
 
5460
         if (flags & ImGuiInputTextFlags_CharsUppercase)
5549
         if (flags & ImGuiInputTextFlags_CharsUppercase)
5461
             if (c >= 'a' && c <= 'z')
5550
             if (c >= 'a' && c <= 'z')
5462
-                *p_char = (c += 'A'-'a');
5551
+                *p_char = (c += (unsigned int)('A'-'a'));
5463
 
5552
 
5464
         if (flags & ImGuiInputTextFlags_CharsNoBlank)
5553
         if (flags & ImGuiInputTextFlags_CharsNoBlank)
5465
             if (ImCharIsSpace(c))
5554
             if (ImCharIsSpace(c))
5471
         ImGuiTextEditCallbackData callback_data;
5560
         ImGuiTextEditCallbackData callback_data;
5472
         memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData));
5561
         memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData));
5473
         callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; 
5562
         callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; 
5474
-        callback_data.EventChar = c;
5563
+        callback_data.EventChar = (ImWchar)c;
5475
         callback_data.Flags = flags;
5564
         callback_data.Flags = flags;
5476
         callback_data.UserData = user_data;
5565
         callback_data.UserData = user_data;
5477
         if (callback(&callback_data) != 0)
5566
         if (callback(&callback_data) != 0)
5526
         {
5615
         {
5527
             // Start edition
5616
             // Start edition
5528
             // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
5617
             // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
5618
+            // From the moment we focused we are ignoring the content of 'buf'
5529
             ImFormatString(edit_state.InitialText, IM_ARRAYSIZE(edit_state.InitialText), "%s", buf);
5619
             ImFormatString(edit_state.InitialText, IM_ARRAYSIZE(edit_state.InitialText), "%s", buf);
5530
-            size_t buf_len = ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), buf, NULL);
5620
+            const char* buf_end = NULL;
5621
+            edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), buf, NULL, &buf_end);
5622
+            edit_state.CurLenA = buf_end - buf; // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
5531
             edit_state.Width = w;
5623
             edit_state.Width = w;
5532
             edit_state.InputCursorScreenPos = ImVec2(-1.f,-1.f);
5624
             edit_state.InputCursorScreenPos = ImVec2(-1.f,-1.f);
5533
             edit_state.CursorAnimReset();
5625
             edit_state.CursorAnimReset();
5544
             {
5636
             {
5545
                 // Recycle existing cursor/selection/undo stack but clamp position
5637
                 // Recycle existing cursor/selection/undo stack but clamp position
5546
                 // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
5638
                 // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
5547
-                edit_state.StbState.cursor = ImMin(edit_state.StbState.cursor, buf_len);
5548
-                edit_state.StbState.select_start = ImMin(edit_state.StbState.select_start, buf_len);
5549
-                edit_state.StbState.select_end = ImMin(edit_state.StbState.select_end, buf_len);
5639
+                edit_state.StbState.cursor = ImMin(edit_state.StbState.cursor, (int)edit_state.CurLenW);
5640
+                edit_state.StbState.select_start = ImMin(edit_state.StbState.select_start, (int)edit_state.CurLenW);
5641
+                edit_state.StbState.select_end = ImMin(edit_state.StbState.select_end, (int)edit_state.CurLenW);
5550
             }
5642
             }
5551
             if (focus_requested_by_tab || (user_clicked && is_ctrl_down))
5643
             if (focus_requested_by_tab || (user_clicked && is_ctrl_down))
5552
                 select_all = true;
5644
                 select_all = true;
5575
     if (g.ActiveId == id)
5667
     if (g.ActiveId == id)
5576
     {
5668
     {
5577
         // Edit in progress
5669
         // Edit in progress
5578
-        edit_state.BufSize = buf_size < IM_ARRAYSIZE(edit_state.Text) ? buf_size : IM_ARRAYSIZE(edit_state.Text);
5670
+        edit_state.BufSizeA = buf_size;
5579
         edit_state.Font = window->Font();
5671
         edit_state.Font = window->Font();
5580
         edit_state.FontSize = window->FontSize();
5672
         edit_state.FontSize = window->FontSize();
5581
-    
5673
+
5582
         const float mx = g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x;
5674
         const float mx = g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x;
5583
         const float my = window->FontSize()*0.5f;   // Flatten mouse because we are doing a single-line edit
5675
         const float my = window->FontSize()*0.5f;   // Flatten mouse because we are doing a single-line edit
5584
 
5676
 
5643
             if (g.IO.SetClipboardTextFn)
5735
             if (g.IO.SetClipboardTextFn)
5644
             {
5736
             {
5645
                 const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0;
5737
                 const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0;
5646
-                const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : (int)ImStrlenW(edit_state.Text);
5738
+                const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : (int)edit_state.CurLenW;
5647
                 ImTextStrToUtf8(text_tmp_utf8, IM_ARRAYSIZE(text_tmp_utf8), edit_state.Text+ib, edit_state.Text+ie);
5739
                 ImTextStrToUtf8(text_tmp_utf8, IM_ARRAYSIZE(text_tmp_utf8), edit_state.Text+ib, edit_state.Text+ie);
5648
                 g.IO.SetClipboardTextFn(text_tmp_utf8);
5740
                 g.IO.SetClipboardTextFn(text_tmp_utf8);
5649
             }
5741
             }
5659
                 if (const char* clipboard = g.IO.GetClipboardTextFn())
5751
                 if (const char* clipboard = g.IO.GetClipboardTextFn())
5660
                 {
5752
                 {
5661
                     // Remove new-line from pasted buffer
5753
                     // Remove new-line from pasted buffer
5662
-                    size_t clipboard_len = strlen(clipboard);
5754
+                    const size_t clipboard_len = strlen(clipboard);
5663
                     ImWchar* clipboard_filtered = (ImWchar*)ImGui::MemAlloc((clipboard_len+1) * sizeof(ImWchar));
5755
                     ImWchar* clipboard_filtered = (ImWchar*)ImGui::MemAlloc((clipboard_len+1) * sizeof(ImWchar));
5664
                     int clipboard_filtered_len = 0;
5756
                     int clipboard_filtered_len = 0;
5665
                     for (const char* s = clipboard; *s; )
5757
                     for (const char* s = clipboard; *s; )
5729
                     callback_data.EventFlag = event_flag; 
5821
                     callback_data.EventFlag = event_flag; 
5730
                     callback_data.EventKey = event_key;
5822
                     callback_data.EventKey = event_key;
5731
                     callback_data.Buf = text_tmp_utf8;
5823
                     callback_data.Buf = text_tmp_utf8;
5732
-                    callback_data.BufSize = edit_state.BufSize;
5824
+                    callback_data.BufSize = edit_state.BufSizeA;
5733
                     callback_data.BufDirty = false;
5825
                     callback_data.BufDirty = false;
5734
                     callback_data.Flags = flags;
5826
                     callback_data.Flags = flags;
5735
                     callback_data.UserData = user_data;
5827
                     callback_data.UserData = user_data;
5736
 
5828
 
5737
                     // We have to convert from position from wchar to UTF-8 positions
5829
                     // We have to convert from position from wchar to UTF-8 positions
5738
-                    const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromWchar(edit_state.Text, edit_state.Text + edit_state.StbState.cursor);
5739
-                    const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromWchar(edit_state.Text, edit_state.Text + edit_state.StbState.select_start);
5740
-                    const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromWchar(edit_state.Text, edit_state.Text + edit_state.StbState.select_end);
5830
+                    const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(edit_state.Text, edit_state.Text + edit_state.StbState.cursor);
5831
+                    const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(edit_state.Text, edit_state.Text + edit_state.StbState.select_start);
5832
+                    const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(edit_state.Text, edit_state.Text + edit_state.StbState.select_end);
5741
 
5833
 
5742
                     // Call user code
5834
                     // Call user code
5743
                     callback(&callback_data);
5835
                     callback(&callback_data);
5744
 
5836
 
5745
                     // Read back what user may have modified
5837
                     // Read back what user may have modified
5746
                     IM_ASSERT(callback_data.Buf == text_tmp_utf8);             // Invalid to modify those fields
5838
                     IM_ASSERT(callback_data.Buf == text_tmp_utf8);             // Invalid to modify those fields
5747
-                    IM_ASSERT(callback_data.BufSize == edit_state.BufSize);
5839
+                    IM_ASSERT(callback_data.BufSize == edit_state.BufSizeA);
5748
                     IM_ASSERT(callback_data.Flags == flags);
5840
                     IM_ASSERT(callback_data.Flags == flags);
5749
                     if (callback_data.CursorPos != utf8_cursor_pos)            edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos);
5841
                     if (callback_data.CursorPos != utf8_cursor_pos)            edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos);
5750
                     if (callback_data.SelectionStart != utf8_selection_start)  edit_state.StbState.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart);
5842
                     if (callback_data.SelectionStart != utf8_selection_start)  edit_state.StbState.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart);
6406
     window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
6498
     window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
6407
     window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y));
6499
     window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y));
6408
 
6500
 
6409
-    window->SizeContentsFit = ImMax(window->SizeContentsFit, ImVec2(window->DC.CursorPosPrevLine.x - window->Pos.x, window->DC.CursorPos.y + window->ScrollY - window->Pos.y));
6501
+    window->SizeContentsCurrent = ImMax(window->SizeContentsCurrent, ImVec2(window->DC.CursorPosPrevLine.x - window->Pos.x, window->DC.CursorPos.y + window->ScrollY - window->Pos.y));
6410
 
6502
 
6411
     window->DC.PrevLineHeight = line_height;
6503
     window->DC.PrevLineHeight = line_height;
6412
     window->DC.CurrentLineHeight = 0.0f;
6504
     window->DC.CurrentLineHeight = 0.0f;
6536
     const float t = window->DC.ColumnsOffsetsT[column_index];
6628
     const float t = window->DC.ColumnsOffsetsT[column_index];
6537
 
6629
 
6538
     const float min_x = window->DC.ColumnsStartX;
6630
     const float min_x = window->DC.ColumnsStartX;
6539
-    const float max_x = window->Size.x - (g.Style.ScrollBarWidth);// - window->WindowPadding().x;
6631
+    const float max_x = window->Size.x - (g.Style.ScrollbarWidth);// - window->WindowPadding().x;
6540
     const float offset = min_x + t * (max_x - min_x);
6632
     const float offset = min_x + t * (max_x - min_x);
6541
     return offset;
6633
     return offset;
6542
 }
6634
 }
6552
     const ImGuiID column_id = window->DC.ColumnsSetID + ImGuiID(column_index);
6644
     const ImGuiID column_id = window->DC.ColumnsSetID + ImGuiID(column_index);
6553
 
6645
 
6554
     const float min_x = window->DC.ColumnsStartX;
6646
     const float min_x = window->DC.ColumnsStartX;
6555
-    const float max_x = window->Size.x - (g.Style.ScrollBarWidth);// - window->WindowPadding().x;
6647
+    const float max_x = window->Size.x - (g.Style.ScrollbarWidth);// - window->WindowPadding().x;
6556
     const float t = (offset - min_x) / (max_x - min_x);
6648
     const float t = (offset - min_x) / (max_x - min_x);
6557
     window->DC.StateStorage->SetFloat(column_id, t);
6649
     window->DC.StateStorage->SetFloat(column_id, t);
6558
     window->DC.ColumnsOffsetsT[column_index] = t;
6650
     window->DC.ColumnsOffsetsT[column_index] = t;
7536
     static const ImWchar ranges[] =
7628
     static const ImWchar ranges[] =
7537
     {
7629
     {
7538
         0x0020, 0x00FF, // Basic Latin + Latin Supplement
7630
         0x0020, 0x00FF, // Basic Latin + Latin Supplement
7539
-        0x3000, 0x3000, // Ideographic Space
7540
-        0x3040, 0x30FF, // Hiragana, Katakana
7631
+        0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
7541
         0x31F0, 0x31FF, // Katakana Phonetic Extensions
7632
         0x31F0, 0x31FF, // Katakana Phonetic Extensions
7542
         0xFF00, 0xFFEF, // Half-width characters
7633
         0xFF00, 0xFFEF, // Half-width characters
7543
         0x4e00, 0x9FAF, // CJK Ideograms
7634
         0x4e00, 0x9FAF, // CJK Ideograms
7586
         109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38,
7677
         109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38,
7587
     };
7678
     };
7588
     static int ranges_unpacked = false;
7679
     static int ranges_unpacked = false;
7589
-    static ImWchar ranges[10 + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1] =
7680
+    static ImWchar ranges[8 + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1] =
7590
     {
7681
     {
7591
         0x0020, 0x00FF, // Basic Latin + Latin Supplement
7682
         0x0020, 0x00FF, // Basic Latin + Latin Supplement
7592
-        0x3000, 0x3000, // Ideographic Space
7593
-        0x3040, 0x30FF, // Hiragana, Katakana
7683
+        0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
7594
         0x31F0, 0x31FF, // Katakana Phonetic Extensions
7684
         0x31F0, 0x31FF, // Katakana Phonetic Extensions
7595
         0xFF00, 0xFFEF, // Half-width characters
7685
         0xFF00, 0xFFEF, // Half-width characters
7596
     };
7686
     };
7598
     {
7688
     {
7599
         // Unpack
7689
         // Unpack
7600
         int codepoint = 0x4e00;
7690
         int codepoint = 0x4e00;
7601
-        ImWchar* dst = &ranges[10];
7691
+        ImWchar* dst = &ranges[8];
7602
         for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2)
7692
         for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2)
7603
             dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1));
7693
             dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1));
7604
         dst[0] = 0;
7694
         dst[0] = 0;
7670
 
7760
 
7671
 // Convert UTF-8 to 32-bits character, process single character input.
7761
 // Convert UTF-8 to 32-bits character, process single character input.
7672
 // Based on stb_from_utf8() from github.com/nothings/stb/
7762
 // Based on stb_from_utf8() from github.com/nothings/stb/
7763
+// We handle UTF-8 decoding error by skipping forward.
7673
 static int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
7764
 static int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
7674
 {
7765
 {
7675
     unsigned int c = (unsigned int)-1;
7766
     unsigned int c = (unsigned int)-1;
7682
     }
7773
     }
7683
     if ((*str & 0xe0) == 0xc0) 
7774
     if ((*str & 0xe0) == 0xc0) 
7684
     {
7775
     {
7685
-        if (in_text_end && in_text_end - (const char*)str < 2) return -1;
7686
-        if (*str < 0xc2) return -1;
7776
+        *out_char = 0;
7777
+        if (in_text_end && in_text_end - (const char*)str < 2) return 0; 
7778
+        if (*str < 0xc2) return 0;
7687
         c = (unsigned int)((*str++ & 0x1f) << 6);
7779
         c = (unsigned int)((*str++ & 0x1f) << 6);
7688
-        if ((*str & 0xc0) != 0x80) return -1;
7780
+        if ((*str & 0xc0) != 0x80) return 0;
7689
         c += (*str++ & 0x3f);
7781
         c += (*str++ & 0x3f);
7690
         *out_char = c;
7782
         *out_char = c;
7691
         return 2;
7783
         return 2;
7692
     }
7784
     }
7693
     if ((*str & 0xf0) == 0xe0) 
7785
     if ((*str & 0xf0) == 0xe0) 
7694
     {
7786
     {
7695
-        if (in_text_end && in_text_end - (const char*)str < 3) return -1;
7696
-        if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return -1;
7697
-        if (*str == 0xed && str[1] > 0x9f) return -1; // str[1] < 0x80 is checked below
7787
+        *out_char = 0;
7788
+        if (in_text_end && in_text_end - (const char*)str < 3) return 0;
7789
+        if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 0;
7790
+        if (*str == 0xed && str[1] > 0x9f) return 0; // str[1] < 0x80 is checked below
7698
         c = (unsigned int)((*str++ & 0x0f) << 12);
7791
         c = (unsigned int)((*str++ & 0x0f) << 12);
7699
-        if ((*str & 0xc0) != 0x80) return -1;
7792
+        if ((*str & 0xc0) != 0x80) return 0;
7700
         c += (unsigned int)((*str++ & 0x3f) << 6);
7793
         c += (unsigned int)((*str++ & 0x3f) << 6);
7701
-        if ((*str & 0xc0) != 0x80) return -1;
7794
+        if ((*str & 0xc0) != 0x80) return 0;
7702
         c += (*str++ & 0x3f);
7795
         c += (*str++ & 0x3f);
7703
         *out_char = c;
7796
         *out_char = c;
7704
         return 3;
7797
         return 3;
7705
     }
7798
     }
7706
     if ((*str & 0xf8) == 0xf0) 
7799
     if ((*str & 0xf8) == 0xf0) 
7707
     {
7800
     {
7708
-        if (in_text_end && in_text_end - (const char*)str < 4) return -1;
7709
-        if (*str > 0xf4) return -1;
7710
-        if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return -1;
7711
-        if (*str == 0xf4 && str[1] > 0x8f) return -1; // str[1] < 0x80 is checked below
7801
+        *out_char = 0;
7802
+        if (in_text_end && in_text_end - (const char*)str < 4) return 0;
7803
+        if (*str > 0xf4) return 0;
7804
+        if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 0;
7805
+        if (*str == 0xf4 && str[1] > 0x8f) return 0; // str[1] < 0x80 is checked below
7712
         c = (unsigned int)((*str++ & 0x07) << 18);
7806
         c = (unsigned int)((*str++ & 0x07) << 18);
7713
-        if ((*str & 0xc0) != 0x80) return -1;
7807
+        if ((*str & 0xc0) != 0x80) return 0;
7714
         c += (unsigned int)((*str++ & 0x3f) << 12);
7808
         c += (unsigned int)((*str++ & 0x3f) << 12);
7715
-        if ((*str & 0xc0) != 0x80) return -1;
7809
+        if ((*str & 0xc0) != 0x80) return 0;
7716
         c += (unsigned int)((*str++ & 0x3f) << 6);
7810
         c += (unsigned int)((*str++ & 0x3f) << 6);
7717
-        if ((*str & 0xc0) != 0x80) return -1;
7811
+        if ((*str & 0xc0) != 0x80) return 0;
7718
         c += (*str++ & 0x3f);
7812
         c += (*str++ & 0x3f);
7719
         // utf-8 encodings of values used in surrogate pairs are invalid
7813
         // utf-8 encodings of values used in surrogate pairs are invalid
7720
-        if ((c & 0xFFFFF800) == 0xD800) return -1;
7814
+        if ((c & 0xFFFFF800) == 0xD800) return 0;
7721
         *out_char = c;
7815
         *out_char = c;
7722
         return 4;
7816
         return 4;
7723
     }
7817
     }
7725
     return 0;
7819
     return 0;
7726
 }
7820
 }
7727
 
7821
 
7728
-static ptrdiff_t ImTextStrFromUtf8(ImWchar* buf, size_t buf_size, const char* in_text, const char* in_text_end)
7822
+static ptrdiff_t ImTextStrFromUtf8(ImWchar* buf, size_t buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)
7729
 {
7823
 {
7730
     ImWchar* buf_out = buf;
7824
     ImWchar* buf_out = buf;
7731
     ImWchar* buf_end = buf + buf_size;
7825
     ImWchar* buf_end = buf + buf_size;
7733
     {
7827
     {
7734
         unsigned int c;
7828
         unsigned int c;
7735
         in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
7829
         in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
7830
+        if (c == 0)
7831
+            break;
7736
         if (c < 0x10000)    // FIXME: Losing characters that don't fit in 2 bytes
7832
         if (c < 0x10000)    // FIXME: Losing characters that don't fit in 2 bytes
7737
             *buf_out++ = (ImWchar)c;
7833
             *buf_out++ = (ImWchar)c;
7738
     }
7834
     }
7739
     *buf_out = 0;
7835
     *buf_out = 0;
7836
+    if (in_text_remaining)
7837
+        *in_text_remaining = in_text;
7740
     return buf_out - buf;
7838
     return buf_out - buf;
7741
 }
7839
 }
7742
 
7840
 
7747
     {
7845
     {
7748
         unsigned int c;
7846
         unsigned int c;
7749
         in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
7847
         in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
7848
+        if (c == 0)
7849
+            break;
7750
         if (c < 0x10000)
7850
         if (c < 0x10000)
7751
             char_count++;
7851
             char_count++;
7752
     }
7852
     }
7811
     return buf_out - buf;
7911
     return buf_out - buf;
7812
 }
7912
 }
7813
 
7913
 
7814
-static int ImTextCountUtf8BytesFromWchar(const ImWchar* in_text, const ImWchar* in_text_end)
7914
+static int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
7815
 {
7915
 {
7816
     int bytes_count = 0;
7916
     int bytes_count = 0;
7817
     while ((!in_text_end || in_text < in_text_end) && *in_text)
7917
     while ((!in_text_end || in_text < in_text_end) && *in_text)
7857
             next_s = s + 1;
7957
             next_s = s + 1;
7858
         else
7958
         else
7859
             next_s = s + ImTextCharFromUtf8(&c, s, text_end);
7959
             next_s = s + ImTextCharFromUtf8(&c, s, text_end);
7960
+        if (c == 0)
7961
+            break;
7860
 
7962
 
7861
         if (c == '\n')
7963
         if (c == '\n')
7862
         {
7964
         {
7958
         // Decode and advance source (handle unlikely UTF-8 decoding failure by skipping to the next byte)
8060
         // Decode and advance source (handle unlikely UTF-8 decoding failure by skipping to the next byte)
7959
         unsigned int c = (unsigned int)*s;
8061
         unsigned int c = (unsigned int)*s;
7960
         if (c < 0x80)
8062
         if (c < 0x80)
8063
+        {
7961
             s += 1;
8064
             s += 1;
8065
+        }
7962
         else
8066
         else
8067
+        {
7963
             s += ImTextCharFromUtf8(&c, s, text_end);
8068
             s += ImTextCharFromUtf8(&c, s, text_end);
8069
+            if (c == 0)
8070
+                break;
8071
+        }
7964
         
8072
         
7965
         if (c == '\n')
8073
         if (c == '\n')
7966
         {
8074
         {
8090
         // Decode and advance source (handle unlikely UTF-8 decoding failure by skipping to the next byte)
8198
         // Decode and advance source (handle unlikely UTF-8 decoding failure by skipping to the next byte)
8091
         unsigned int c = (unsigned int)*s;
8199
         unsigned int c = (unsigned int)*s;
8092
         if (c < 0x80)
8200
         if (c < 0x80)
8201
+        {
8093
             s += 1;
8202
             s += 1;
8203
+        }
8094
         else
8204
         else
8205
+        {
8095
             s += ImTextCharFromUtf8(&c, s, text_end);
8206
             s += ImTextCharFromUtf8(&c, s, text_end);
8207
+            if (c == 0)
8208
+                break;
8209
+        }
8096
 
8210
 
8097
         if (c == '\n')
8211
         if (c == '\n')
8098
         {
8212
         {
8190
     }
8304
     }
8191
     if (!OpenClipboard(NULL)) 
8305
     if (!OpenClipboard(NULL)) 
8192
         return NULL;
8306
         return NULL;
8193
-    HANDLE buf_handle = GetClipboardData(CF_TEXT); 
8194
-    if (buf_handle == NULL)
8307
+    HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT); 
8308
+    if (wbuf_handle == NULL)
8195
         return NULL;
8309
         return NULL;
8196
-    if (char* buf_global = (char*)GlobalLock(buf_handle))
8197
-        buf_local = ImStrdup(buf_global);
8198
-    GlobalUnlock(buf_handle); 
8310
+    if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle))
8311
+    {
8312
+        int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1;
8313
+        buf_local = (char*)ImGui::MemAlloc(buf_len * sizeof(char));
8314
+        ImTextStrToUtf8(buf_local, buf_len, wbuf_global, NULL);
8315
+    }
8316
+    GlobalUnlock(wbuf_handle); 
8199
     CloseClipboard(); 
8317
     CloseClipboard(); 
8200
     return buf_local;
8318
     return buf_local;
8201
 }
8319
 }
8205
 {
8323
 {
8206
     if (!OpenClipboard(NULL))
8324
     if (!OpenClipboard(NULL))
8207
         return;
8325
         return;
8208
-    const char* text_end = text + strlen(text);
8209
-    const int buf_length = (int)(text_end - text) + 1;
8210
-    HGLOBAL buf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)buf_length * sizeof(char)); 
8211
-    if (buf_handle == NULL)
8326
+
8327
+    const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1;
8328
+    HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); 
8329
+    if (wbuf_handle == NULL)
8212
         return;
8330
         return;
8213
-    char* buf_global = (char *)GlobalLock(buf_handle); 
8214
-    memcpy(buf_global, text, (size_t)(text_end - text));
8215
-    buf_global[text_end - text] = 0;
8216
-    GlobalUnlock(buf_handle); 
8331
+    ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle); 
8332
+    ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL);
8333
+    GlobalUnlock(wbuf_handle); 
8217
     EmptyClipboard();
8334
     EmptyClipboard();
8218
-    SetClipboardData(CF_TEXT, buf_handle);
8335
+    SetClipboardData(CF_UNICODETEXT, wbuf_handle);
8219
     CloseClipboard();
8336
     CloseClipboard();
8220
 }
8337
 }
8221
 
8338
 
8333
         ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
8450
         ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
8334
         ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
8451
         ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
8335
         ImGui::SliderFloat("TreeNodeSpacing", &style.TreeNodeSpacing, 0.0f, 20.0f, "%.0f");
8452
         ImGui::SliderFloat("TreeNodeSpacing", &style.TreeNodeSpacing, 0.0f, 20.0f, "%.0f");
8336
-        ImGui::SliderFloat("ScrollBarWidth", &style.ScrollBarWidth, 0.0f, 20.0f, "%.0f");
8453
+        ImGui::SliderFloat("ScrollBarWidth", &style.ScrollbarWidth, 1.0f, 20.0f, "%.0f");
8454
+        ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
8337
         ImGui::TreePop();
8455
         ImGui::TreePop();
8338
     }
8456
     }
8339
 
8457
 
8410
 // Demonstrate ImGui features (unfortunately this makes this function a little bloated!)
8528
 // Demonstrate ImGui features (unfortunately this makes this function a little bloated!)
8411
 void ImGui::ShowTestWindow(bool* opened)
8529
 void ImGui::ShowTestWindow(bool* opened)
8412
 {
8530
 {
8531
+    // Examples apps
8532
+    static bool show_app_console = false;
8533
+    static bool show_app_long_text = false;
8534
+    static bool show_app_auto_resize = false;
8535
+    static bool show_app_fixed_overlay = false;
8536
+    static bool show_app_custom_rendering = false;
8537
+    static bool show_app_manipulating_window_title = false;
8538
+    if (show_app_console)
8539
+        ShowExampleAppConsole(&show_app_console);
8540
+    if (show_app_long_text)
8541
+        ShowExampleAppLongText(&show_app_long_text);
8542
+    if (show_app_auto_resize)
8543
+        ShowExampleAppAutoResize(&show_app_auto_resize);
8544
+    if (show_app_fixed_overlay)
8545
+        ShowExampleAppFixedOverlay(&show_app_fixed_overlay);
8546
+    if (show_app_manipulating_window_title)
8547
+        ShowExampleAppManipulatingWindowTitle(&show_app_manipulating_window_title);
8548
+    if (show_app_custom_rendering)
8549
+        ShowExampleAppCustomRendering(&show_app_custom_rendering);
8550
+
8413
     static bool no_titlebar = false;
8551
     static bool no_titlebar = false;
8414
     static bool no_border = true;
8552
     static bool no_border = true;
8415
     static bool no_resize = false;
8553
     static bool no_resize = false;
9114
         }
9252
         }
9115
     }
9253
     }
9116
 
9254
 
9117
-    static bool show_app_console = false;
9118
-    static bool show_app_long_text = false;
9119
-    static bool show_app_auto_resize = false;
9120
-    static bool show_app_fixed_overlay = false;
9121
-    static bool show_app_custom_rendering = false;
9122
-    static bool show_app_manipulating_window_title = false;
9123
     if (ImGui::CollapsingHeader("App Examples"))
9255
     if (ImGui::CollapsingHeader("App Examples"))
9124
     {
9256
     {
9125
         ImGui::Checkbox("Console", &show_app_console);
9257
         ImGui::Checkbox("Console", &show_app_console);
9129
         ImGui::Checkbox("Manipulating window title", &show_app_manipulating_window_title);
9261
         ImGui::Checkbox("Manipulating window title", &show_app_manipulating_window_title);
9130
         ImGui::Checkbox("Custom rendering", &show_app_custom_rendering);
9262
         ImGui::Checkbox("Custom rendering", &show_app_custom_rendering);
9131
     }
9263
     }
9132
-    if (show_app_console)
9133
-        ShowExampleAppConsole(&show_app_console);
9134
-    if (show_app_long_text)
9135
-        ShowExampleAppLongText(&show_app_long_text);
9136
-    if (show_app_auto_resize)
9137
-        ShowExampleAppAutoResize(&show_app_auto_resize);
9138
-    if (show_app_fixed_overlay)
9139
-        ShowExampleAppFixedOverlay(&show_app_fixed_overlay);
9140
-    if (show_app_manipulating_window_title)
9141
-        ShowExampleAppManipulatingWindowTitle(&show_app_manipulating_window_title);
9142
-    if (show_app_custom_rendering)
9143
-        ShowExampleAppCustomRendering(&show_app_custom_rendering);
9144
 
9264
 
9145
     ImGui::End();
9265
     ImGui::End();
9146
 }
9266
 }
9180
 
9300
 
9181
 static void ShowExampleAppManipulatingWindowTitle(bool* opened)
9301
 static void ShowExampleAppManipulatingWindowTitle(bool* opened)
9182
 {
9302
 {
9303
+    (void)opened;
9304
+
9183
     // By default, Windows are uniquely identified by their title.
9305
     // By default, Windows are uniquely identified by their title.
9184
     // You can use the "##" and "###" markers to manipulate the display/ID. Read FAQ at the top of this file!
9306
     // You can use the "##" and "###" markers to manipulate the display/ID. Read FAQ at the top of this file!
9185
 
9307
 
9205
 
9327
 
9206
 static void ShowExampleAppCustomRendering(bool* opened)
9328
 static void ShowExampleAppCustomRendering(bool* opened)
9207
 {
9329
 {
9330
+    ImGui::SetNextWindowSize(ImVec2(300,350), ImGuiSetCond_FirstUseEver);
9208
     if (!ImGui::Begin("Example: Custom Rendering", opened))
9331
     if (!ImGui::Begin("Example: Custom Rendering", opened))
9209
     {
9332
     {
9210
         ImGui::End();
9333
         ImGui::End();
9219
     static ImVector<ImVec2> points;
9342
     static ImVector<ImVec2> points;
9220
     static bool adding_line = false;
9343
     static bool adding_line = false;
9221
     if (ImGui::Button("Clear")) points.clear();
9344
     if (ImGui::Button("Clear")) points.clear();
9222
-    if (points.size() > 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) points.pop_back(); }
9345
+    if (points.size() >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
9223
     ImGui::Text("Left-click and drag to add lines");
9346
     ImGui::Text("Left-click and drag to add lines");
9224
     ImGui::Text("Right-click to undo");
9347
     ImGui::Text("Right-click to undo");
9225
 
9348
 
9325
         if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.size()); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); 
9448
         if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.size()); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); 
9326
         if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine(); 
9449
         if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine(); 
9327
         if (ImGui::SmallButton("Clear")) ClearLog();
9450
         if (ImGui::SmallButton("Clear")) ClearLog();
9451
+        //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
9452
+
9328
         ImGui::Separator();
9453
         ImGui::Separator();
9329
 
9454
 
9330
         ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
9455
         ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));

+ 16
- 14
src/deps/imgui/imgui.h View File

1
-// ImGui library v1.35 wip
1
+// ImGui library v1.35
2
 // See .cpp file for documentation.
2
 // See .cpp file for documentation.
3
 // See ImGui::ShowTestWindow() for sample code.
3
 // See ImGui::ShowTestWindow() for sample code.
4
 // Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase.
4
 // Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase.
6
 
6
 
7
 #pragma once
7
 #pragma once
8
 
8
 
9
-struct ImDrawCmd;
10
-struct ImDrawList;
11
-struct ImFont;
12
-struct ImFontAtlas;
13
-struct ImGuiAabb;
14
-struct ImGuiIO;
15
-struct ImGuiStorage;
16
-struct ImGuiStyle;
17
-struct ImGuiWindow;
18
-
19
-#include "imconfig.h"
9
+#include "imconfig.h"       // User-editable configuration file
20
 #include <float.h>          // FLT_MAX
10
 #include <float.h>          // FLT_MAX
21
 #include <stdarg.h>         // va_list
11
 #include <stdarg.h>         // va_list
22
 #include <stddef.h>         // ptrdiff_t
12
 #include <stddef.h>         // ptrdiff_t
34
 #define IMGUI_API
24
 #define IMGUI_API
35
 #endif
25
 #endif
36
 
26
 
27
+// Forward declarations
28
+struct ImDrawCmd;
29
+struct ImDrawList;
30
+struct ImFont;
31
+struct ImFontAtlas;
32
+struct ImGuiIO;
33
+struct ImGuiStorage;
34
+struct ImGuiStyle;
35
+
37
 typedef unsigned int ImU32;
36
 typedef unsigned int ImU32;
38
 typedef unsigned short ImWchar;     // character for display
37
 typedef unsigned short ImWchar;     // character for display
39
 typedef void* ImTextureID;          // user data to refer to a texture (e.g. store your texture handle/id)
38
 typedef void* ImTextureID;          // user data to refer to a texture (e.g. store your texture handle/id)
191
     IMGUI_API void          SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond = 0);   // set named window collapsed state.
190
     IMGUI_API void          SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond = 0);   // set named window collapsed state.
192
     IMGUI_API void          SetWindowFocus(const char* name);                                              // set named window to be focused / front-most
191
     IMGUI_API void          SetWindowFocus(const char* name);                                              // set named window to be focused / front-most
193
 
192
 
193
+    IMGUI_API float         GetScrollPosY();                                                    // get scrolling position (0..GetScrollMaxY())
194
+    IMGUI_API float         GetScrollMaxY();                                                    // get maximum scrolling position == ContentSize.Y - WindowSize.Y
194
     IMGUI_API void          SetScrollPosHere();                                                 // adjust scrolling position to center into the current cursor position.
195
     IMGUI_API void          SetScrollPosHere();                                                 // adjust scrolling position to center into the current cursor position.
195
     IMGUI_API void          SetKeyboardFocusHere(int offset = 0);                               // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget.
196
     IMGUI_API void          SetKeyboardFocusHere(int offset = 0);                               // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget.
196
     IMGUI_API void          SetStateStorage(ImGuiStorage* tree);                                // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it).
197
     IMGUI_API void          SetStateStorage(ImGuiStorage* tree);                                // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it).
385
     ImGuiWindowFlags_NoTitleBar             = 1 << 0,   // Disable title-bar
386
     ImGuiWindowFlags_NoTitleBar             = 1 << 0,   // Disable title-bar
386
     ImGuiWindowFlags_NoResize               = 1 << 1,   // Disable user resizing with the lower-right grip
387
     ImGuiWindowFlags_NoResize               = 1 << 1,   // Disable user resizing with the lower-right grip
387
     ImGuiWindowFlags_NoMove                 = 1 << 2,   // Disable user moving the window
388
     ImGuiWindowFlags_NoMove                 = 1 << 2,   // Disable user moving the window
388
-    ImGuiWindowFlags_NoScrollbar            = 1 << 3,   // Disable scroll bar (window can still scroll with mouse or programatically)
389
+    ImGuiWindowFlags_NoScrollbar            = 1 << 3,   // Disable scrollbar (window can still scroll with mouse or programatically)
389
     ImGuiWindowFlags_NoScrollWithMouse      = 1 << 4,   // Disable user scrolling with mouse wheel
390
     ImGuiWindowFlags_NoScrollWithMouse      = 1 << 4,   // Disable user scrolling with mouse wheel
390
     ImGuiWindowFlags_NoCollapse             = 1 << 5,   // Disable user collapsing window by double-clicking on it
391
     ImGuiWindowFlags_NoCollapse             = 1 << 5,   // Disable user collapsing window by double-clicking on it
391
     ImGuiWindowFlags_AlwaysAutoResize       = 1 << 6,   // Resize every window to its content every frame
392
     ImGuiWindowFlags_AlwaysAutoResize       = 1 << 6,   // Resize every window to its content every frame
533
     float       WindowFillAlphaDefault;     // Default alpha of window background, if not specified in ImGui::Begin()
534
     float       WindowFillAlphaDefault;     // Default alpha of window background, if not specified in ImGui::Begin()
534
     float       TreeNodeSpacing;            // Horizontal spacing when entering a tree node
535
     float       TreeNodeSpacing;            // Horizontal spacing when entering a tree node
535
     float       ColumnsMinSpacing;          // Minimum horizontal spacing between two columns
536
     float       ColumnsMinSpacing;          // Minimum horizontal spacing between two columns
536
-    float       ScrollBarWidth;             // Width of the vertical scroll bar
537
+    float       ScrollbarWidth;             // Width of the vertical scrollbar
538
+    float       GrabMinSize;                // Minimum width/height of a slider or scrollbar grab
537
     ImVec4      Colors[ImGuiCol_COUNT];
539
     ImVec4      Colors[ImGuiCol_COUNT];
538
 
540
 
539
     IMGUI_API ImGuiStyle();
541
     IMGUI_API ImGuiStyle();

+ 2
- 0
src/loader/LoaderTR2.cpp View File

1120
         return;
1120
         return;
1121
     }
1121
     }
1122
 
1122
 
1123
+    Log::get(LOG_INFO) << "LoaderTR2: Loading \"" << f << "\"" << Log::endl;
1124
+
1123
     int riffCount = loadSoundFiles(sfx);
1125
     int riffCount = loadSoundFiles(sfx);
1124
     if (riffCount > 0)
1126
     if (riffCount > 0)
1125
         Log::get(LOG_INFO) << "LoaderTR2: Loaded " << riffCount << " SoundSamples" << Log::endl;
1127
         Log::get(LOG_INFO) << "LoaderTR2: Loaded " << riffCount << " SoundSamples" << Log::endl;

+ 6
- 0
src/system/Sound.cpp View File

84
 #endif
84
 #endif
85
 }
85
 }
86
 
86
 
87
+void Sound::stop(int source) {
88
+#ifdef USING_AL
89
+    SoundAL::stop(source);
90
+#endif
91
+}
92
+
87
 void Sound::stopAll() {
93
 void Sound::stopAll() {
88
 #ifdef USING_AL
94
 #ifdef USING_AL
89
     SoundAL::stopAll();
95
     SoundAL::stopAll();

+ 10
- 0
src/system/SoundAL.cpp View File

222
     }
222
     }
223
 }
223
 }
224
 
224
 
225
+void SoundAL::stop(int source) {
226
+    if (!init)
227
+        return;
228
+
229
+    if ((source >= 0) && (source < sources.size()))
230
+        alSourceStop(sources.at(source));
231
+    else
232
+        Log::get(LOG_ERROR) << "SoundAL: Can't stop non-existing source!" << Log::endl;
233
+}
234
+
225
 void SoundAL::stopAll() {
235
 void SoundAL::stopAll() {
226
     if (!init)
236
     if (!init)
227
         return;
237
         return;

Loading…
Cancel
Save