summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autobuild.xml56
-rw-r--r--indra/CMakeLists.txt1
-rw-r--r--indra/cmake/CMakeLists.txt2
-rw-r--r--indra/cmake/LLMeshOptimizer.cmake7
-rw-r--r--indra/cmake/MESHOPTIMIZER.cmake16
-rw-r--r--indra/llmeshoptimizer/CMakeLists.txt44
-rw-r--r--indra/llmeshoptimizer/llmeshoptimizer.cpp108
-rw-r--r--indra/llmeshoptimizer/llmeshoptimizer.h75
-rw-r--r--indra/newview/CMakeLists.txt3
-rw-r--r--indra/newview/app_settings/key_bindings.xml8
-rw-r--r--indra/newview/llfloatermodelpreview.cpp27
-rw-r--r--indra/newview/llkeyconflict.cpp66
-rw-r--r--indra/newview/llkeyconflict.h4
-rw-r--r--indra/newview/llmodelpreview.cpp295
-rw-r--r--indra/newview/llmodelpreview.h14
-rw-r--r--indra/newview/lltoolcomp.cpp10
-rw-r--r--indra/newview/lltoolpie.cpp2
-rw-r--r--indra/newview/llviewerinput.cpp81
-rw-r--r--indra/newview/llviewerinput.h5
-rw-r--r--indra/newview/skins/default/xui/en/control_table_contents_media.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_preview.xml32
21 files changed, 832 insertions, 34 deletions
diff --git a/autobuild.xml b/autobuild.xml
index eb057ec8e0..8f5770f5b2 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -2394,6 +2394,62 @@
<key>version</key>
<string>7.11.1.297294</string>
</map>
+ <key>meshoptimizer</key>
+ <map>
+ <key>canonical_repo</key>
+ <string>https://bitbucket.org/lindenlab/3p-meshoptimizer</string>
+ <key>copyright</key>
+ <string>Copyright (c) 2016-2021 Arseny Kapoulkine</string>
+ <key>description</key>
+ <string>Meshoptimizer. Mesh optimization library.</string>
+ <key>license</key>
+ <string>meshoptimizer</string>
+ <key>license_file</key>
+ <string>LICENSES/meshoptimizer.txt</string>
+ <key>name</key>
+ <string>meshoptimizer</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>30bc37db57bbd87c4b5f62634964242a</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/84218/784918/meshoptimizer-0.16.561408-darwin64-561408.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>ca3684bcf0447746cd2844e94f6d1fc7</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/84219/784924/meshoptimizer-0.16.561408-windows-561408.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows</string>
+ </map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>aef28c089d20f69d13c9c3e113fb3895</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/84220/784931/meshoptimizer-0.16.561408-windows64-561408.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>0.16.561408</string>
+ </map>
<key>nghttp2</key>
<map>
<key>copyright</key>
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index db88e44127..fcc1b28ebb 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -38,6 +38,7 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llkdu)
add_subdirectory(${LIBS_OPEN_PREFIX}llimagej2coj)
add_subdirectory(${LIBS_OPEN_PREFIX}llinventory)
add_subdirectory(${LIBS_OPEN_PREFIX}llmath)
+add_subdirectory(${LIBS_OPEN_PREFIX}llmeshoptimizer)
add_subdirectory(${LIBS_OPEN_PREFIX}llmessage)
add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive)
add_subdirectory(${LIBS_OPEN_PREFIX}llrender)
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index a17e37cd32..527a9cba43 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -61,6 +61,7 @@ set(cmake_SOURCE_FILES
LLKDU.cmake
LLLogin.cmake
LLMath.cmake
+ LLMeshOptimizer.cmake
LLMessage.cmake
LLPhysicsExtensions.cmake
LLPlugin.cmake
@@ -74,6 +75,7 @@ set(cmake_SOURCE_FILES
LLXML.cmake
Linking.cmake
MediaPluginBase.cmake
+ MESHOPTIMIZER.cmake
NDOF.cmake
OPENAL.cmake
OpenGL.cmake
diff --git a/indra/cmake/LLMeshOptimizer.cmake b/indra/cmake/LLMeshOptimizer.cmake
new file mode 100644
index 0000000000..b79944f618
--- /dev/null
+++ b/indra/cmake/LLMeshOptimizer.cmake
@@ -0,0 +1,7 @@
+# -*- cmake -*-
+
+set(LLMESHOPTIMIZER_INCLUDE_DIRS
+ ${LIBS_OPEN_DIR}/llmeshoptimizer
+ )
+
+set(LLMESHOPTIMIZER_LIBRARIES llmeshoptimizer)
diff --git a/indra/cmake/MESHOPTIMIZER.cmake b/indra/cmake/MESHOPTIMIZER.cmake
new file mode 100644
index 0000000000..1c5b47b9bd
--- /dev/null
+++ b/indra/cmake/MESHOPTIMIZER.cmake
@@ -0,0 +1,16 @@
+# -*- cmake -*-
+
+include(Linking)
+include(Prebuilt)
+
+use_prebuilt_binary(meshoptimizer)
+
+if (WINDOWS)
+ set(MESHOPTIMIZER_LIBRARIES meshoptimizer.lib)
+elseif (LINUX)
+ set(MESHOPTIMIZER_LIBRARIES meshoptimizer.o)
+elseif (DARWIN)
+ set(MESHOPTIMIZER_LIBRARIES libmeshoptimizer.a)
+endif (WINDOWS)
+
+set(MESHOPTIMIZER_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/meshoptimizer)
diff --git a/indra/llmeshoptimizer/CMakeLists.txt b/indra/llmeshoptimizer/CMakeLists.txt
new file mode 100644
index 0000000000..016794cfad
--- /dev/null
+++ b/indra/llmeshoptimizer/CMakeLists.txt
@@ -0,0 +1,44 @@
+# -*- cmake -*-
+
+project(llmeshoptimizer)
+
+include(MESHOPTIMIZER)
+
+include(00-Common)
+include(LLCommon)
+include(LLMath)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLMESHOPTIMIZER_INCLUDE_DIR}
+ ${MESHOPTIMIZER_INCLUDE_DIRS}
+ ${LIBS_PREBUILT_DIR}/include #access to boost headers, needed for LLError
+ )
+
+set(llmeshoptimizer_SOURCE_FILES
+ llmeshoptimizer.cpp
+ )
+
+set(llmeshoptimizer_HEADER_FILES
+ CMakeLists.txt
+
+ llmeshoptimizer.h
+ )
+
+set_source_files_properties(${llmeshoptimizer_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND llmeshoptimizer_SOURCE_FILES ${llmeshoptimizer_HEADER_FILES})
+
+#if (USE_MESHOPT)
+ add_library (llmeshoptimizer ${llmeshoptimizer_SOURCE_FILES})
+
+ target_link_libraries(llmeshoptimizer
+ ${LLCOMMON_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${MESHOPTIMIZER_LIBRARIES})
+
+ # Add tests
+
+#endif (USE_MESHOPT)
diff --git a/indra/llmeshoptimizer/llmeshoptimizer.cpp b/indra/llmeshoptimizer/llmeshoptimizer.cpp
new file mode 100644
index 0000000000..09fa7cb235
--- /dev/null
+++ b/indra/llmeshoptimizer/llmeshoptimizer.cpp
@@ -0,0 +1,108 @@
+ /**
+* @file llmeshoptimizer.cpp
+* @brief Wrapper around meshoptimizer
+*
+* $LicenseInfo:firstyear=2021&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2021, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "llmeshoptimizer.h"
+
+#include "meshoptimizer.h"
+
+LLMeshOptimizer::LLMeshOptimizer()
+{
+ // Todo: Looks like for memory management, we can add allocator and deallocator callbacks
+ // Should be one time
+ // meshopt_setAllocator(allocate, deallocate);
+}
+
+LLMeshOptimizer::~LLMeshOptimizer()
+{
+}
+
+//static
+void LLMeshOptimizer::generateShadowIndexBuffer(U16 *destination,
+ const U16 *indices,
+ U64 index_count,
+ const LLVector4a *vertex_positions,
+ U64 vertex_count,
+ U64 vertex_positions_stride
+)
+{
+ meshopt_generateShadowIndexBuffer<unsigned short>(destination,
+ indices,
+ index_count,
+ (const float*)vertex_positions, // verify that it is correct to convert to float
+ vertex_count,
+ sizeof(LLVector4a),
+ vertex_positions_stride
+ );
+}
+
+//static
+U64 LLMeshOptimizer::simplify(U16 *destination,
+ const U16 *indices,
+ U64 index_count,
+ const LLVector4a *vertex_positions,
+ U64 vertex_count,
+ U64 vertex_positions_stride,
+ U64 target_index_count,
+ F32 target_error,
+ F32* result_error
+ )
+{
+
+ return meshopt_simplify<unsigned short>(destination,
+ indices,
+ index_count,
+ (const float*)vertex_positions,
+ vertex_count,
+ vertex_positions_stride,
+ target_index_count,
+ target_error,
+ result_error
+ );
+}
+
+//static
+U64 LLMeshOptimizer::simplifySloppy(U16 *destination,
+ const U16 *indices,
+ U64 index_count,
+ const LLVector4a *vertex_positions,
+ U64 vertex_count,
+ U64 vertex_positions_stride,
+ U64 target_index_count,
+ F32 target_error,
+ F32* result_error
+ )
+{
+ return meshopt_simplifySloppy<unsigned short>(destination,
+ indices,
+ index_count,
+ (const float*)vertex_positions,
+ vertex_count,
+ vertex_positions_stride,
+ target_index_count,
+ target_error,
+ result_error
+ );
+}
diff --git a/indra/llmeshoptimizer/llmeshoptimizer.h b/indra/llmeshoptimizer/llmeshoptimizer.h
new file mode 100644
index 0000000000..1aa02372fa
--- /dev/null
+++ b/indra/llmeshoptimizer/llmeshoptimizer.h
@@ -0,0 +1,75 @@
+/**
+* @file llmeshoptimizer.h
+* @brief Wrapper around meshoptimizer
+*
+* $LicenseInfo:firstyear=2021&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2021, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+#ifndef LLMESHOPTIMIZER_H
+#define LLMESHOPTIMIZER_H
+
+#include "linden_common.h"
+
+#include "llmath.h"
+
+class LLMeshOptimizer
+{
+public:
+ LLMeshOptimizer();
+ ~LLMeshOptimizer();
+
+ static void generateShadowIndexBuffer(
+ U16 *destination,
+ const U16 *indices,
+ U64 index_count,
+ const LLVector4a *vertex_positions,
+ U64 vertex_count,
+ U64 vertex_positions_stride);
+
+ // returns amount of indices in destiantion
+ // result_error returns how far from original the model is in % if not NULL
+ static U64 simplify(
+ U16 *destination,
+ const U16 *indices,
+ U64 index_count,
+ const LLVector4a *vertex_positions,
+ U64 vertex_count,
+ U64 vertex_positions_stride,
+ U64 target_index_count,
+ F32 target_error,
+ F32* result_error);
+
+ // returns amount of indices in destiantion
+ // result_error returns how far from original the model is in % if not NULL
+ static U64 simplifySloppy(
+ U16 *destination,
+ const U16 *indices,
+ U64 index_count,
+ const LLVector4a *vertex_positions,
+ U64 vertex_count,
+ U64 vertex_positions_stride,
+ U64 target_index_count,
+ F32 target_error,
+ F32* result_error);
+private:
+};
+
+#endif //LLMESHOPTIMIZER_H
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 87caca56af..13e17075d8 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -31,6 +31,7 @@ include(LLInventory)
include(LLKDU)
include(LLLogin)
include(LLMath)
+include(LLMeshOptimizer)
include(LLMessage)
include(LLPhysicsExtensions)
include(LLPlugin)
@@ -77,6 +78,7 @@ include_directories(
${LLKDU_INCLUDE_DIRS}
${LLINVENTORY_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
+ ${LLMESHOPTIMIZER_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
${LLPLUGIN_INCLUDE_DIRS}
${LLPRIMITIVE_INCLUDE_DIRS}
@@ -2029,6 +2031,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${LLCHARACTER_LIBRARIES}
${LLIMAGE_LIBRARIES}
${LLINVENTORY_LIBRARIES}
+ ${LLMESHOPTIMIZER_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLPLUGIN_LIBRARIES}
${LLPRIMITIVE_LIBRARIES}
diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml
index 4f6deb1f98..ffc1b2e7cc 100644
--- a/indra/newview/app_settings/key_bindings.xml
+++ b/indra/newview/app_settings/key_bindings.xml
@@ -33,6 +33,8 @@
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="sript_trigger_lbutton"/>
</first_person>
<third_person>
<binding key="A" mask="NONE" command="turn_left"/>
@@ -127,6 +129,8 @@
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
<binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="sript_trigger_lbutton"/>
</third_person>
<sitting>
<binding key="A" mask="ALT" command="spin_around_cw"/>
@@ -224,6 +228,8 @@
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="sript_trigger_lbutton"/>
</sitting>
<edit_avatar>
<!--Avatar editing camera controls-->
@@ -251,5 +257,7 @@
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="sript_trigger_lbutton"/>
</edit_avatar>
</keys>
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index d9edd4dc30..d61311d610 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -139,7 +139,7 @@ mAvatarTabIndex(0)
mLODMode[LLModel::LOD_HIGH] = 0;
for (U32 i = 0; i < LLModel::LOD_HIGH; i++)
{
- mLODMode[i] = 1;
+ mLODMode[i] = LLModelPreview::MESH_OPTIMIZER;
}
}
@@ -722,7 +722,23 @@ void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata)
void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
{
- mModelPreview->onLODParamCommit(lod, enforce_tri_limit);
+ LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]);
+ S32 mode = lod_source_combo->getCurrentIndex();
+ switch (mode)
+ {
+ case LLModelPreview::GENERATE:
+ mModelPreview->onLODGenerateParamCommit(lod, enforce_tri_limit);
+ break;
+ case LLModelPreview::MESH_OPTIMIZER:
+ mModelPreview->onLODMeshOptimizerParamCommit(lod, enforce_tri_limit, false);
+ break;
+ case LLModelPreview::MESH_OPTIMIZER_SLOPPY:
+ mModelPreview->onLODMeshOptimizerParamCommit(lod, enforce_tri_limit, true);
+ break;
+ default:
+ LL_ERRS() << "Only supposed to be called to generate models" << LL_ENDL;
+ break;
+ }
//refresh LoDs that reference this one
for (S32 i = lod - 1; i >= 0; --i)
@@ -1721,7 +1737,10 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
refresh();
LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]);
- if (lod_source_combo->getCurrentIndex() == LLModelPreview::GENERATE)
+ S32 index = lod_source_combo->getCurrentIndex();
+ if (index == LLModelPreview::GENERATE
+ || index == LLModelPreview::MESH_OPTIMIZER
+ || index == LLModelPreview::MESH_OPTIMIZER_SLOPPY)
{ //rebuild LoD to update triangle counts
onLODParamCommit(lod, true);
}
@@ -1752,7 +1771,7 @@ void LLFloaterModelPreview::resetUploadOptions()
getChild<LLComboBox>("lod_source_" + lod_name[NUM_LOD - 1])->setCurrentByIndex(LLModelPreview::LOD_FROM_FILE);
for (S32 lod = 0; lod < NUM_LOD - 1; ++lod)
{
- getChild<LLComboBox>("lod_source_" + lod_name[lod])->setCurrentByIndex(LLModelPreview::GENERATE);
+ getChild<LLComboBox>("lod_source_" + lod_name[lod])->setCurrentByIndex(LLModelPreview::MESH_OPTIMIZER);
childSetValue("lod_file_" + lod_name[lod], "");
}
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index b6107eeedf..58a740e16a 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -730,13 +730,19 @@ void LLKeyConflictHandler::resetToDefault(const std::string &control_name, U32 i
{
return;
}
+ LLKeyConflict &type_data = mControlsMap[control_name];
+ if (!type_data.mAssignable)
+ {
+ return;
+ }
LLKeyData data = getDefaultControl(control_name, index);
- if (data != mControlsMap[control_name].getKeyData(index))
+ if (data != type_data.getKeyData(index))
{
// reset controls that might have been switched to our current control
removeConflicts(data, mControlsMap[control_name].mConflictMask);
mControlsMap[control_name].setKeyData(data, index);
+ mHasUnsavedChanges = true;
}
}
@@ -862,7 +868,7 @@ void LLKeyConflictHandler::resetKeyboardBindings()
void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
{
- // These controls are meant to cause conflicts when user tries to assign same control somewhere else
+ // These placeholds are meant to cause conflict resolution when user tries to assign same control somewhere else
// also this can be used to pre-record controls that should not conflict or to assign conflict groups/masks
if (load_mode == MODE_FIRST_PERSON)
@@ -922,25 +928,73 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
registerTemporaryControl("spin_around_ccw_sitting");
registerTemporaryControl("spin_around_cw_sitting");
}
+
+
+ // Special case, mouse clicks passed to scripts have 'lowest' piority
+ // thus do not conflict, everything else has a chance before them
+ // also in ML they have highest priority, but only when script-grabbed,
+ // thus do not conflict
+ // (see AGENT_CONTROL_ML_LBUTTON_DOWN and CONTROL_LBUTTON_DOWN_INDEX)
+ LLKeyConflict *type_data = &mControlsMap[script_mouse_handler_name];
+ type_data->mAssignable = true;
+ type_data->mConflictMask = U32_MAX - CONFLICT_LMOUSE;
}
-bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask)
+bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, U32 conlict_mask)
{
if (conlict_mask == CONFLICT_NOTHING)
{
// Can't conflict
return true;
}
+
+ if (data.mMouse == CLICK_LEFT
+ && data.mMask == MASK_NONE
+ && data.mKey == KEY_NONE)
+ {
+ if ((conlict_mask & CONFLICT_LMOUSE) == 0)
+ {
+ // Can't conflict
+ return true;
+ }
+ else
+ {
+ // simplify conflict mask
+ conlict_mask = CONFLICT_LMOUSE;
+ }
+ }
+ else
+ {
+ // simplify conflict mask
+ conlict_mask &= ~CONFLICT_LMOUSE;
+ }
+
std::map<std::string, S32> conflict_list;
control_map_t::iterator cntrl_iter = mControlsMap.begin();
control_map_t::iterator cntrl_end = mControlsMap.end();
for (; cntrl_iter != cntrl_end; ++cntrl_iter)
{
+ const U32 cmp_mask = cntrl_iter->second.mConflictMask;
+ if ((cmp_mask & conlict_mask) == 0)
+ {
+ // can't conflict
+ continue;
+ }
S32 index = cntrl_iter->second.mKeyBind.findKeyData(data);
- if (index >= 0
- && cntrl_iter->second.mConflictMask != CONFLICT_NOTHING
- && (cntrl_iter->second.mConflictMask & conlict_mask) != 0)
+ if (index >= 0)
{
+ if (cmp_mask != U32_MAX)
+ {
+ const LLKeyData cmp_data = cntrl_iter->second.mKeyBind.getKeyData(index);
+ if ((cmp_mask & CONFLICT_LMOUSE) == 0
+ && cmp_data.mMouse == CLICK_LEFT
+ && cmp_data.mMask == MASK_NONE
+ && cmp_data.mKey == KEY_NONE)
+ {
+ // Does not conflict
+ continue;
+ }
+ }
if (cntrl_iter->second.mAssignable)
{
// Potentially we can have multiple conflict flags conflicting
diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h
index 2926ca3aeb..e78d2fa33b 100644
--- a/indra/newview/llkeyconflict.h
+++ b/indra/newview/llkeyconflict.h
@@ -66,6 +66,7 @@ public:
};
const U32 CONFLICT_NOTHING = 0;
+ const U32 CONFLICT_LMOUSE = 0x1 << 1;
// at the moment this just means that key will conflict with everything that is identical
const U32 CONFLICT_ANY = U32_MAX;
@@ -145,6 +146,7 @@ private:
// at the moment these kind of control is not savable, but takes part in conflict resolution
void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask);
+ // conflict mask 0 means that any conflicts will be ignored
void registerTemporaryControl(const std::string &control_name, U32 conflict_mask = 0);
typedef std::map<std::string, LLKeyConflict> control_map_t;
@@ -152,7 +154,7 @@ private:
bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination);
void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values
// returns false in case user is trying to reuse control that can't be reassigned
- bool removeConflicts(const LLKeyData &data, const U32 &conlict_mask);
+ bool removeConflicts(const LLKeyData &data, U32 conlict_mask);
// removes flags and removes temporary file, returns 'true' if file was removed
bool clearUnsavedChanges();
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index a9e80ab5da..93186657ce 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -41,6 +41,7 @@
#include "lliconctrl.h"
#include "llmatrix4a.h"
#include "llmeshrepository.h"
+#include "llmeshoptimizer.h"
#include "llrender.h"
#include "llsdutil_math.h"
#include "llskinningutil.h"
@@ -1339,8 +1340,9 @@ void LLModelPreview::restoreNormals()
updateStatusMessages();
}
-void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)
+void LLModelPreview::genGlodLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)
{
+ LL_INFOS() << "Generating lod " << which_lod << " using glod" << LL_ENDL;
// Allow LoD from -1 to LLModel::LOD_PHYSICS
if (which_lod < -1 || which_lod > LLModel::NUM_LODS - 1)
{
@@ -1403,7 +1405,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
- U32 lod_mode = 0;
+ U32 lod_mode = LIMIT_TRIANGLES;
F32 lod_error_threshold = 0;
@@ -1424,7 +1426,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
mRequestedLoDMode[which_lod] = lod_mode;
}
- if (lod_mode == 0)
+ if (lod_mode == LIMIT_TRIANGLES)
{
lod_mode = GLOD_TRIANGLE_BUDGET;
@@ -1704,6 +1706,276 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
}
}
+void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit, bool sloppy)
+{
+ LL_INFOS() << "Generating lod " << which_lod << " using meshoptimizer" << LL_ENDL;
+ // Allow LoD from -1 to LLModel::LOD_PHYSICS
+ if (which_lod < -1 || which_lod > LLModel::NUM_LODS - 1)
+ {
+ std::ostringstream out;
+ out << "Invalid level of detail: " << which_lod;
+ LL_WARNS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ assert(lod >= -1 && lod < LLModel::NUM_LODS);
+ return;
+ }
+
+ if (mBaseModel.empty())
+ {
+ return;
+ }
+
+ //get the triangle count for all base models
+ S32 base_triangle_count = 0;
+ for (S32 i = 0; i < mBaseModel.size(); ++i)
+ {
+ base_triangle_count += mBaseModel[i]->getNumTriangles();
+ }
+
+ // Urgh...
+ // TODO: add interface to mFMP to get error treshold or let mFMP write one into LLModelPreview
+ // We should not be accesing views from other class!
+ U32 lod_mode = LIMIT_TRIANGLES;
+ F32 indices_ratio = 0;
+ F32 triangle_limit = 0;
+ F32 lod_error_threshold = 1; //100%
+
+ // If requesting a single lod
+ if (which_lod > -1 && which_lod < NUM_LOD)
+ {
+ LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode_" + lod_name[which_lod]);
+ if (iface)
+ {
+ lod_mode = iface->getFirstSelectedIndex();
+ }
+
+ if (lod_mode == LIMIT_TRIANGLES)
+ {
+ if (!enforce_tri_limit)
+ {
+ triangle_limit = base_triangle_count;
+ // reset to default value for this lod
+ F32 pw = pow((F32)decimation, (F32)(LLModel::LOD_HIGH - which_lod));
+
+ triangle_limit /= pw; //indices_ratio can be 1/pw
+ }
+ else
+ {
+
+ // UI spacifies limit for all models of single lod
+ triangle_limit = mFMP->childGetValue("lod_triangle_limit_" + lod_name[which_lod]).asInteger();
+
+ }
+ // meshoptimizer doesn't use triangle limit, it uses indices limit, so convert it to aproximate ratio
+ indices_ratio = triangle_limit / (F32)base_triangle_count;
+ }
+ else
+ {
+ lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[which_lod]).asReal();
+ }
+ }
+ else
+ {
+ // we are genrating all lods and each lod will get own indices_ratio
+ indices_ratio = 1;
+ triangle_limit = base_triangle_count;
+ }
+
+ mMaxTriangleLimit = base_triangle_count;
+
+ // TODO: Glod regenerates vertex buffer at this stage
+ // check why, it might be needed to regenerate buffer as well
+
+ // Build models
+
+ S32 start = LLModel::LOD_HIGH;
+ S32 end = 0;
+
+ if (which_lod != -1)
+ {
+ start = which_lod;
+ end = which_lod;
+ }
+
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ if (shader)
+ {
+ shader->unbind();
+ }
+
+ for (S32 lod = start; lod >= end; --lod)
+ {
+ if (which_lod == -1)
+ {
+ // we are genrating all lods and each lod gets own indices_ratio
+ if (lod < start)
+ {
+ indices_ratio /= decimation;
+ triangle_limit /= decimation;
+ }
+ }
+
+ mRequestedTriangleCount[lod] = triangle_limit;
+ mRequestedErrorThreshold[lod] = lod_error_threshold;
+ mRequestedLoDMode[lod] = lod_mode;
+
+ mModel[lod].clear();
+ mModel[lod].resize(mBaseModel.size());
+ mVertexBuffer[lod].clear();
+
+
+ for (U32 mdl_idx = 0; mdl_idx < mBaseModel.size(); ++mdl_idx)
+ {
+ LLModel* base = mBaseModel[mdl_idx];
+
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+ mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f);
+
+ std::string name = base->mLabel + getLodSuffix(lod);
+
+ mModel[lod][mdl_idx]->mLabel = name;
+ mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID;
+ mModel[lod][mdl_idx]->setNumVolumeFaces(base->getNumVolumeFaces());
+
+ LLModel* target_model = mModel[lod][mdl_idx];
+
+ // Run meshoptimizer for each face
+ for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
+ {
+ const LLVolumeFace &face = base->getVolumeFace(face_idx);
+ S32 num_indices = face.mNumIndices;
+ // todo: do not allocate per each face, add one large buffer somewhere
+ // faces have limited amount of indices
+ S32 size = (num_indices * sizeof(U16) + 0xF) & ~0xF;
+ U16* output = (U16*)ll_aligned_malloc_16(size);
+
+ /*
+ generateShadowIndexBuffer appears to deform model
+ LLMeshOptimizer::generateShadowIndexBuffer(
+ &shadow[0],
+ face.mIndices,
+ num_indices,
+ &face.mPositions[0],
+ face.mNumVertices);
+ */
+
+ S32 target_indices = llmax(3, llfloor(num_indices * indices_ratio)); // leave at least one triangle
+ F32 result_code = 0; // how far from original the model is, 1 == 100%
+ S32 new_indices = 0;
+
+ if (sloppy)
+ {
+ new_indices = LLMeshOptimizer::simplifySloppy(
+ output,
+ face.mIndices,
+ num_indices,
+ face.mPositions,
+ face.mNumVertices,
+ LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX],
+ target_indices,
+ lod_error_threshold,
+ &result_code);
+ }
+
+ // todo: instead of checking (new_indices <= 0)
+ // create a dummy triangle if simplifySloppy returns nothing
+ if (new_indices <= 0)
+ {
+ new_indices = LLMeshOptimizer::simplify(
+ output,
+ face.mIndices,
+ num_indices,
+ face.mPositions,
+ face.mNumVertices,
+ LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX],
+ target_indices,
+ lod_error_threshold,
+ &result_code);
+ }
+
+
+ if (result_code < 0)
+ {
+ LL_WARNS() << "Negative result code from meshoptimizer for face " << face_idx
+ << " of model " << target_model->mLabel
+ << " target Indices: " << target_indices
+ << " new Indices: " << new_indices
+ << " original count: " << num_indices << LL_ENDL;
+ }
+ if (new_indices == 0)
+ {
+ LL_WARNS() << "No indices generated by meshoptimizer for face " << face_idx
+ << " of model " << target_model->mLabel
+ << " target Indices: " << target_indices
+ << " original count: " << num_indices << LL_ENDL;
+ }
+
+ LLVolumeFace &new_face = target_model->getVolumeFace(face_idx);
+
+ // Copy old values
+ new_face = face;
+
+ // Assign new values
+ new_face.resizeIndices(new_indices); // will wipe out mIndices, so new_face can't substitute output
+ S32 idx_size = (new_indices * sizeof(U16) + 0xF) & ~0xF;
+ LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output, idx_size);
+
+ ll_aligned_free_16(output);
+
+ // clear unused values
+ new_face.optimize();
+ }
+
+ //blind copy skin weights and just take closest skin weight to point on
+ //decimated mesh for now (auto-generating LODs with skin weights is still a bit
+ //of an open problem).
+ target_model->mPosition = base->mPosition;
+ target_model->mSkinWeights = base->mSkinWeights;
+ target_model->mSkinInfo = base->mSkinInfo;
+
+ //copy material list
+ target_model->mMaterialList = base->mMaterialList;
+
+ if (!validate_model(target_model))
+ {
+ LL_ERRS() << "Invalid model generated when creating LODs" << LL_ENDL;
+ }
+ }
+
+ //rebuild scene based on mBaseScene
+ mScene[lod].clear();
+ mScene[lod] = mBaseScene;
+
+ for (U32 i = 0; i < mBaseModel.size(); ++i)
+ {
+ LLModel* mdl = mBaseModel[i];
+ LLModel* target = mModel[lod][i];
+ if (target)
+ {
+ for (LLModelLoader::scene::iterator iter = mScene[lod].begin(); iter != mScene[lod].end(); ++iter)
+ {
+ for (U32 j = 0; j < iter->second.size(); ++j)
+ {
+ if (iter->second[j].mModel == mdl)
+ {
+ iter->second[j].mModel = target;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ mResourceCost = calcResourceCost();
+
+ LLVertexBuffer::unbind();
+ if (shader)
+ {
+ shader->bind();
+ }
+}
+
void LLModelPreview::updateStatusMessages()
{
// bit mask values for physics errors. used to prevent overwrite of single line status
@@ -2957,7 +3229,7 @@ BOOL LLModelPreview::render()
{
genBuffers(-1, skin_weight);
//genBuffers(3);
- //genLODs();
+ //genGlodLODs();
}
if (!mModel[mPreviewLOD].empty())
@@ -3544,7 +3816,7 @@ bool LLModelPreview::lodQueryCallback()
{
S32 lod = preview->mLodsQuery.back();
preview->mLodsQuery.pop_back();
- preview->genLODs(lod);
+ preview->genMeshOptimizerLODs(lod);
if (preview->mLookUpLodFiles && (lod == LLModel::LOD_HIGH))
{
@@ -3559,11 +3831,20 @@ bool LLModelPreview::lodQueryCallback()
return true;
}
-void LLModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
+void LLModelPreview::onLODGenerateParamCommit(S32 lod, bool enforce_tri_limit)
+{
+ if (!mLODFrozen)
+ {
+ genGlodLODs(lod, 3, enforce_tri_limit);
+ refresh();
+ }
+}
+
+void LLModelPreview::onLODMeshOptimizerParamCommit(S32 requested_lod, bool enforce_tri_limit, bool sloppy)
{
if (!mLODFrozen)
{
- genLODs(lod, 3, enforce_tri_limit);
+ genMeshOptimizerLODs(requested_lod, 3, enforce_tri_limit, sloppy);
refresh();
}
}
diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h
index 3664a27a72..9f38156ca2 100644
--- a/indra/newview/llmodelpreview.h
+++ b/indra/newview/llmodelpreview.h
@@ -125,9 +125,17 @@ public:
{
LOD_FROM_FILE = 0,
GENERATE,
+ MESH_OPTIMIZER,
+ MESH_OPTIMIZER_SLOPPY,
USE_LOD_ABOVE,
} eLoDMode;
+ typedef enum
+ {
+ LIMIT_TRIANGLES = 0,
+ LIMIT_ERROR_TRESHOLD,
+ } eLoDLimit;
+
public:
// Todo: model preview shouldn't need floater dependency, it
// should just expose data to floater, not control flaoter like it does
@@ -155,7 +163,8 @@ public:
void loadModelCallback(S32 lod);
bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); }
void queryLODs() { mGenLOD = true; };
- void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
+ void genGlodLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
+ void genMeshOptimizerLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false, bool sloppy = false);
void generateNormals();
void restoreNormals();
U32 calcResourceCost();
@@ -166,7 +175,8 @@ public:
void updateStatusMessages();
void updateLodControls(S32 lod);
void clearGLODGroup();
- void onLODParamCommit(S32 lod, bool enforce_tri_limit);
+ void onLODGenerateParamCommit(S32 lod, bool enforce_tri_limit);
+ void onLODMeshOptimizerParamCommit(S32 lod, bool enforce_tri_limit, bool sloppy);
void addEmptyFace(LLModel* pTarget);
const bool getModelPivot(void) const { return mHasPivot; }
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index f9c327b46e..9ac1810964 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -44,6 +44,7 @@
#include "lltoolmgr.h"
#include "lltoolselectrect.h"
#include "lltoolplacer.h"
+#include "llviewerinput.h"
#include "llviewermenu.h"
#include "llviewerobject.h"
#include "llviewerwindow.h"
@@ -743,7 +744,7 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
{
// if the left button is grabbed, don't put up the pie menu
- if (gAgent.leftButtonGrabbed())
+ if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
{
gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
return FALSE;
@@ -760,7 +761,7 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// if the left button is grabbed, don't put up the pie menu
- if (gAgent.leftButtonGrabbed())
+ if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
{
gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
return FALSE;
@@ -794,7 +795,10 @@ BOOL LLToolCompGun::handleRightMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleMouseUp(S32 x, S32 y, MASK mask)
{
- gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ if (gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ }
setCurrentTool( (LLTool*) mGun );
return TRUE;
}
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 75a5fabdc2..0693775622 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -746,7 +746,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
else if (!mMouseOutsideSlop
&& mMouseButtonDown
// disable camera steering if click on land is not used for moving
- && gViewerInput.isMouseBindUsed(CLICK_LEFT))
+ && gViewerInput.isMouseBindUsed(CLICK_LEFT, MASK_NONE, MODE_THIRD_PERSON))
{
S32 delta_x = x - mMouseDownX;
S32 delta_y = y - mMouseDownY;
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index c0eaa88f54..8b3d406b78 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -61,7 +61,7 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
const LLKeyData agent_control_lbutton(CLICK_LEFT, KEY_NONE, MASK_NONE, true);
struct LLKeyboardActionRegistry
-: public LLRegistrySingleton<std::string, boost::function<bool (EKeystate keystate)>, LLKeyboardActionRegistry>
+: public LLRegistrySingleton<const std::string, boost::function<bool (EKeystate keystate)>, LLKeyboardActionRegistry>
{
LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry);
};
@@ -836,7 +836,49 @@ bool voice_follow_key(EKeystate s)
return false;
}
-bool agen_control_lbutton_handle(EKeystate s)
+bool sript_trigger_lbutton(EKeystate s)
+{
+ // Check for script overriding/expecting left mouse button.
+ // Note that this does not pass event further and depends onto mouselook.
+ // Checks CONTROL_ML_LBUTTON_DOWN_INDEX for mouselook,
+ // CONTROL_LBUTTON_DOWN_INDEX for normal camera
+ if (gAgent.leftButtonGrabbed())
+ {
+ bool mouselook = gAgentCamera.cameraMouselook();
+ switch (s)
+ {
+ case KEYSTATE_DOWN:
+ // at the moment sript_trigger_lbutton is only intended for mouselook
+ // but handling other modes just in case
+ if (mouselook)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
+ }
+ else
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
+ }
+ return true;
+ case KEYSTATE_UP:
+ if (mouselook)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ }
+ else
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
+ }
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+// Used by scripts, for overriding/handling left mouse button
+// see mControlsTakenCount
+bool agent_control_lbutton_handle(EKeystate s)
{
switch (s)
{
@@ -905,6 +947,7 @@ REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to);
REGISTER_KEYBOARD_ACTION("walk_to", walk_to);
REGISTER_KEYBOARD_ACTION("toggle_voice", toggle_voice);
REGISTER_KEYBOARD_ACTION("voice_follow_key", voice_follow_key);
+REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, sript_trigger_lbutton);
#undef REGISTER_KEYBOARD_ACTION
LLViewerInput::LLViewerInput()
@@ -1104,6 +1147,20 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const
typedef boost::function<bool(EKeystate)> function_t;
function_t function = NULL;
+ if (mouse == CLICK_LEFT
+ && mask == MASK_NONE
+ && function_name == script_mouse_handler_name)
+ {
+ // Special case
+ // Left click has script overrides and by default
+ // is handled via agent_control_lbutton as last option
+ // In case of mouselook and present overrides it has highest
+ // priority even over UI and is handled in LLToolCompGun::handleMouseDown
+ // so just mark it as having default handler
+ mLMouseDefaultHandling[mode] = true;
+ return TRUE;
+ }
+
function_t* result = LLKeyboardActionRegistry::getValue(function_name);
if (result)
{
@@ -1164,6 +1221,7 @@ void LLViewerInput::resetBindings()
{
mKeyBindings[i].clear();
mMouseBindings[i].clear();
+ mLMouseDefaultHandling[i] = false;
}
}
@@ -1355,13 +1413,14 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask))
{
+ // pass mouse left button press to script
if (key_down && !repeat)
{
- res = agen_control_lbutton_handle(KEYSTATE_DOWN);
+ res = agent_control_lbutton_handle(KEYSTATE_DOWN);
}
if (key_up)
{
- res = agen_control_lbutton_handle(KEYSTATE_UP);
+ res = agent_control_lbutton_handle(KEYSTATE_UP);
}
}
return res;
@@ -1481,24 +1540,28 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
S32 mode = getMode();
MASK mask = gKeyboard->currentMask(TRUE);
res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state);
+
// no user defined actions found or those actions can't handle the key/button, handle control if nessesary
- if (!res && agent_control_lbutton.canHandle(click, KEY_NONE, mask))
+ // This will pass AGENT_CONTROL_LBUTTON_DOWN to server, no idea why it doesn't do mouselook variant _ML_
+ // but it was set this way forever (moved as is from LLTool::handleMouseDown) so lots of scripts probably
+ // rely on this.
+ if (!res && mLMouseDefaultHandling[mode] && agent_control_lbutton.canHandle(click, KEY_NONE, mask))
{
switch (state)
{
case MOUSE_STATE_DOWN:
- agen_control_lbutton_handle(KEYSTATE_DOWN);
+ agent_control_lbutton_handle(KEYSTATE_DOWN);
res = true;
break;
case MOUSE_STATE_CLICK:
// might not work best with some functions,
// but some function need specific states too specifically
- agen_control_lbutton_handle(KEYSTATE_DOWN);
- agen_control_lbutton_handle(KEYSTATE_UP);
+ agent_control_lbutton_handle(KEYSTATE_DOWN);
+ agent_control_lbutton_handle(KEYSTATE_UP);
res = true;
break;
case MOUSE_STATE_UP:
- agen_control_lbutton_handle(KEYSTATE_UP);
+ agent_control_lbutton_handle(KEYSTATE_UP);
res = true;
break;
default:
diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h
index 281a209896..32dd3c0e28 100644
--- a/indra/newview/llviewerinput.h
+++ b/indra/newview/llviewerinput.h
@@ -31,6 +31,7 @@
#include "llinitparam.h"
const S32 MAX_KEY_BINDINGS = 128; // was 60
+const std::string script_mouse_handler_name = "sript_trigger_lbutton";
class LLNamedFunction
{
@@ -124,7 +125,8 @@ public:
BOOL handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
void scanMouse();
- bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask = MASK_NONE, const S32 mode = MODE_THIRD_PERSON);
+ bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode);
+ bool isLMouseHandlingDefault(const S32 mode) { return mLMouseDefaultHandling[mode]; }
private:
bool scanKey(const std::vector<LLKeyboardBinding> &binding,
@@ -163,6 +165,7 @@ private:
// to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown)
std::vector<LLKeyboardBinding> mKeyBindings[MODE_COUNT];
std::vector<LLMouseBinding> mMouseBindings[MODE_COUNT];
+ bool mLMouseDefaultHandling[MODE_COUNT]; // Due to having special priority
typedef std::map<U32, U32> key_remap_t;
key_remap_t mRemapKeys[MODE_COUNT];
diff --git a/indra/newview/skins/default/xui/en/control_table_contents_media.xml b/indra/newview/skins/default/xui/en/control_table_contents_media.xml
index ce5d3556b6..a97c45dd6f 100644
--- a/indra/newview/skins/default/xui/en/control_table_contents_media.xml
+++ b/indra/newview/skins/default/xui/en/control_table_contents_media.xml
@@ -73,4 +73,14 @@
name="lst_action"
value="Start Gesture" />
</rows>
+ <rows
+ name="sript_trigger_lbutton"
+ value="sript_trigger_lbutton">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Interact (Script LMB)" />
+ </rows>
</contents>
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index 7f863756eb..230284555c 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -176,6 +176,14 @@
name="Generate"
label="Generate"
value="Generate" />
+ <item
+ name="MeshOpt"
+ label="MeshOpt"
+ value="MeshOpt" />
+ <item
+ name="MeshOptSloppy"
+ label="MeshOptSloppy"
+ value="MeshOptSloppy" />
</combo_box>
<line_editor
follows="left|top"
@@ -306,6 +314,14 @@
label="Generate"
value="Generate" />
<item
+ name="MeshOpt"
+ label="MeshOpt"
+ value="MeshOpt" />
+ <item
+ name="MeshOptSloppy"
+ label="MeshOptSloppy"
+ value="MeshOptSloppy" />
+ <item
name="Use LoD above"
label="Use LoD above"
value="Use LoD above" />
@@ -439,6 +455,14 @@
label="Generate"
value="Generate" />
<item
+ name="MeshOpt"
+ label="MeshOpt"
+ value="MeshOpt" />
+ <item
+ name="MeshOptSloppy"
+ label="MeshOptSloppy"
+ value="MeshOptSloppy" />
+ <item
name="Use LoD above"
label="Use LoD above"
value="Use LoD above" />
@@ -572,6 +596,14 @@
label="Generate"
value="Generate" />
<item
+ name="MeshOpt"
+ label="MeshOpt"
+ value="MeshOpt" />
+ <item
+ name="MeshOptSloppy"
+ label="MeshOptSloppy"
+ value="MeshOptSloppy" />
+ <item
name="Use LoD above"
label="Use LoD above"
value="Use LoD above" />