diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/llinventorybridge.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llmaterialeditor.cpp | 207 | ||||
-rw-r--r-- | indra/newview/llmaterialeditor.h | 58 | ||||
-rw-r--r-- | indra/newview/llviewerfloaterreg.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llviewerinventory.cpp | 11 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_material_editor.xml | 374 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_inventory.xml | 8 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_inventory_add.xml | 8 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_viewer.xml | 10 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 1 |
11 files changed, 684 insertions, 1 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e7aa884f6b..0d2b99a8cd 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -404,6 +404,7 @@ set(viewer_SOURCE_FILES llmaniptranslate.cpp llmarketplacefunctions.cpp llmarketplacenotifications.cpp + llmaterialeditor.cpp llmaterialmgr.cpp llmediactrl.cpp llmediadataclient.cpp @@ -1044,6 +1045,7 @@ set(viewer_HEADER_FILES llmaniptranslate.h llmarketplacefunctions.h llmarketplacenotifications.h + llmaterialeditor.h llmaterialmgr.h llmediactrl.h llmediadataclient.h diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a0de3a2af1..a296d2dfef 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4011,6 +4011,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back(std::string("New Note")); disabled_items.push_back(std::string("New Settings")); disabled_items.push_back(std::string("New Gesture")); + disabled_items.push_back(std::string("New Material")); disabled_items.push_back(std::string("New Clothes")); disabled_items.push_back(std::string("New Body Parts")); disabled_items.push_back(std::string("upload_def")); @@ -4038,6 +4039,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back(std::string("New Script")); disabled_items.push_back(std::string("New Note")); disabled_items.push_back(std::string("New Gesture")); + disabled_items.push_back(std::string("New Material")); disabled_items.push_back(std::string("New Clothes")); disabled_items.push_back(std::string("New Body Parts")); disabled_items.push_back(std::string("upload_def")); @@ -4102,6 +4104,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items items.push_back(std::string("New Script")); items.push_back(std::string("New Note")); items.push_back(std::string("New Gesture")); + items.push_back(std::string("New Material")); items.push_back(std::string("New Clothes")); items.push_back(std::string("New Body Parts")); items.push_back(std::string("New Settings")); diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp new file mode 100644 index 0000000000..6e7f7adfed --- /dev/null +++ b/indra/newview/llmaterialeditor.cpp @@ -0,0 +1,207 @@ +/** + * @file llmaterialeditor.cpp + * @brief Implementation of the notecard editor + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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 "llviewerprecompiledheaders.h" + +#include "llmaterialeditor.h" +#include "llcombobox.h" + +#include "tinygltf/tiny_gltf.h" + +///---------------------------------------------------------------------------- +/// Class LLPreviewNotecard +///---------------------------------------------------------------------------- + +// Default constructor +LLMaterialEditor::LLMaterialEditor(const LLSD& key) + : LLFloater(key) +{ +} + +BOOL LLMaterialEditor::postBuild() +{ + childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this)); + return LLFloater::postBuild(); +} + +LLUUID LLMaterialEditor::getAlbedoId() +{ + return childGetValue("albedo texture").asUUID(); +} + +LLColor4 LLMaterialEditor::getAlbedoColor() +{ + LLColor4 ret = LLColor4(childGetValue("albedo color")); + ret.mV[3] = getTransparency(); + return ret; +} + + +F32 LLMaterialEditor::getTransparency() +{ + return childGetValue("transparency").asReal(); +} + +std::string LLMaterialEditor::getAlphaMode() +{ + return childGetValue("alpha mode").asString(); +} + +F32 LLMaterialEditor::getAlphaCutoff() +{ + return childGetValue("alpha cutoff").asReal(); +} + +LLUUID LLMaterialEditor::getMetallicRoughnessId() +{ + return childGetValue("metallic-roughness texture").asUUID(); +} + +F32 LLMaterialEditor::getMetalnessFactor() +{ + return childGetValue("metalness factor").asReal(); +} + +F32 LLMaterialEditor::getRoughnessFactor() +{ + return childGetValue("roughness factor").asReal(); +} + +LLUUID LLMaterialEditor::getEmissiveId() +{ + return childGetValue("emissive texture").asUUID(); +} + +LLColor4 LLMaterialEditor::getEmissiveColor() +{ + return LLColor4(childGetValue("emissive color")); +} + +LLUUID LLMaterialEditor::getNormalId() +{ + return childGetValue("normal texture").asUUID(); +} + +bool LLMaterialEditor::getDoubleSided() +{ + return childGetValue("double sided").asBoolean(); +} + + +static void write_color(const LLColor4& color, std::vector<double>& c) +{ + for (int i = 0; i < c.size(); ++i) // NOTE -- use c.size because some gltf colors are 3-component + { + c[i] = color.mV[i]; + } +} + +static U32 write_texture(const LLUUID& id, tinygltf::Model& model) +{ + tinygltf::Image image; + image.uri = id.asString(); + model.images.push_back(image); + U32 image_idx = model.images.size() - 1; + + tinygltf::Texture texture; + texture.source = image_idx; + model.textures.push_back(texture); + U32 texture_idx = model.textures.size() - 1; + + return texture_idx; +} + +void LLMaterialEditor::onClickSave() +{ + tinygltf::Model model; + model.materials.resize(1); + tinygltf::PbrMetallicRoughness& pbrMaterial = model.materials[0].pbrMetallicRoughness; + + // write albedo + LLColor4 albedo_color = getAlbedoColor(); + albedo_color.mV[3] = getTransparency(); + write_color(albedo_color, pbrMaterial.baseColorFactor); + + model.materials[0].alphaCutoff = getAlphaCutoff(); + model.materials[0].alphaMode = getAlphaMode(); + + LLUUID albedo_id = getAlbedoId(); + + if (albedo_id.notNull()) + { + U32 texture_idx = write_texture(albedo_id, model); + + pbrMaterial.baseColorTexture.index = texture_idx; + } + + // write metallic/roughness + F32 metalness = getMetalnessFactor(); + F32 roughness = getRoughnessFactor(); + + pbrMaterial.metallicFactor = metalness; + pbrMaterial.roughnessFactor = roughness; + + LLUUID mr_id = getMetallicRoughnessId(); + if (mr_id.notNull()) + { + U32 texture_idx = write_texture(mr_id, model); + pbrMaterial.metallicRoughnessTexture.index = texture_idx; + } + + //write emissive + LLColor4 emissive_color = getEmissiveColor(); + model.materials[0].emissiveFactor.resize(3); + write_color(emissive_color, model.materials[0].emissiveFactor); + + LLUUID emissive_id = getEmissiveId(); + if (emissive_id.notNull()) + { + U32 idx = write_texture(emissive_id, model); + model.materials[0].emissiveTexture.index = idx; + } + + //write normal + LLUUID normal_id = getNormalId(); + if (normal_id.notNull()) + { + U32 idx = write_texture(normal_id, model); + model.materials[0].normalTexture.index = idx; + } + + //write doublesided + model.materials[0].doubleSided = getDoubleSided(); + + std::ostringstream str; + + tinygltf::TinyGLTF gltf; + model.asset.version = "2.0"; + gltf.WriteGltfSceneToStream(&model, str, true, false); + + std::string dump = str.str(); + + LL_INFOS() << dump << LL_ENDL; +} + diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h new file mode 100644 index 0000000000..febdb3bbc1 --- /dev/null +++ b/indra/newview/llmaterialeditor.h @@ -0,0 +1,58 @@ +/** + * @file llmaterialeditor.h + * @brief LLMaterialEditor class header file + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#pragma once + +#include "llfloater.h" + +class LLMaterialEditor : public LLFloater +{ +public: + LLMaterialEditor(const LLSD& key); + + void onClickSave(); + + // llpanel + BOOL postBuild() override; + + LLUUID getAlbedoId(); + LLColor4 getAlbedoColor(); + F32 getTransparency(); + std::string getAlphaMode(); + F32 getAlphaCutoff(); + + LLUUID getMetallicRoughnessId(); + F32 getMetalnessFactor(); + F32 getRoughnessFactor(); + + LLUUID getEmissiveId(); + LLColor4 getEmissiveColor(); + + LLUUID getNormalId(); + + bool getDoubleSided(); +}; + diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index dd03d6cfdd..97cb8e2000 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -152,6 +152,7 @@ #include "llinspectobject.h" #include "llinspectremoteobject.h" #include "llinspecttoast.h" +#include "llmaterialeditor.h" #include "llmoveview.h" #include "llfloaterimnearbychat.h" #include "llpanelblockedlist.h" @@ -337,6 +338,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("save_camera_preset", "floater_save_camera_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSaveCameraPreset>); LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptEdPrefs>); + LLFloaterReg::add("material_editor", "floater_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>); + LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>); LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build<LLFloaterTestInspectors>); //LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build<LLFloaterTestListView>); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 55ac817479..d777cde554 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -147,6 +147,7 @@ LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary() mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable"); mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture"); + mInventoryItemsDict["New Material"] = LLTrans::getString("New Material"); mInventoryItemsDict["New Script"] = LLTrans::getString("New Script"); mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder"); mInventoryItemsDict["New Note"] = LLTrans::getString("New Note"); @@ -1672,6 +1673,7 @@ void remove_folder_contents(const LLUUID& category, bool keep_outfit_links, const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not) const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not) const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) +const std::string NEW_MATERIAL_NAME = "New Material"; // *TODO:Translate? (probably not) // ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) @@ -1727,6 +1729,15 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, LLInventoryType::IT_GESTURE, PERM_ALL); // overridden in create_new_item } + else if ("material" == type_name) + { + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); + create_new_item(NEW_GESTURE_NAME, + parent_id, + LLAssetType::AT_MATERIAL, + LLInventoryType::IT_MATERIAL, + PERM_ALL); // overridden in create_new_item + } else if (("sky" == type_name) || ("water" == type_name) || ("daycycle" == type_name)) { LLSettingsType::type_e stype(LLSettingsType::ST_NONE); diff --git a/indra/newview/skins/default/xui/en/floater_material_editor.xml b/indra/newview/skins/default/xui/en/floater_material_editor.xml new file mode 100644 index 0000000000..5d72e6f79d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml @@ -0,0 +1,374 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="false" + default_tab_group="1" + height="777" + layout="topleft" + name="material editor" + help_topic="material_editor" + title="Material: [MATERIAL_NAME]" + width="256"> + <panel + border="true" + follows="left|top" + width="246" + height="196" + layout="topleft" + left="5" + mouse_opaque="false" + name="Texture" + top="20" + > + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="10" + top="5" + width="64"> + Albedo: + </text> + <texture_picker + can_apply_immediately="true" + default_image_name="Default" + fallback_image="materials_ui_x_24.png" + follows="left|top" + top_pad="8" + height="151" + layout="topleft" + left="10" + name="albedo texture" + tool_tip="Albedo map. Alpha channel is optional and used for transparency." + width="128" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_pad="5" + top_delta="-15" + > + Tint + </text> + <color_swatch + can_apply_immediately="true" + follows="left|top" + height="40" + label_height="0" + layout="topleft" + left_delta="0" + top_pad="5" + name="albedo color" + width="40" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_delta="0" + top_pad="5" + width="96" + > + Transparency + </text> + <spinner + decimal_digits="3" + follows="left|top" + height="19" + increment="0.01" + initial_value="1" + layout="topleft" + left_delta="0" + top_pad="5" + max_val="1" + name="transparency" + width="64" + /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_delta="0" + name="label alphamode" + text_readonly_color="LabelDisabledColor" + top_pad="5" + width="90"> + Alpha mode + </text> + <combo_box + height="23" + layout="topleft" + left_delta="0" + name="alpha mode" + top_pad="4" + width="96"> + <combo_box.item + label="None" + name="None" + value="OPAQUE" /> + <combo_box.item + label="Alpha blending" + name="Alpha blending" + value="BLEND" /> + <combo_box.item + label="Alpha masking" + name="Alpha masking" + value="MASK" /> + </combo_box> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_delta="0" + top_pad="5" + width="96" + > + Alpha Cutoff + </text> + <spinner + decimal_digits="3" + follows="left|top" + height="19" + increment="0.01" + initial_value="1" + layout="topleft" + left_delta="0" + top_pad="5" + max_val="1" + name="alpha cutoff" + width="64" + /> + </panel> + <panel + border="true" + follows="left|top" + width="246" + height="160" + layout="topleft" + left="5" + mouse_opaque="false" + name="Texture" + top_pad="5" + > + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="10" + top_pad="5" + > + Metallic-Roughness: + </text> + <texture_picker + can_apply_immediately="true" + default_image_name="Default" + fallback_image="materials_ui_x_24.png" + follows="left|top" + width="128" + height="151" + layout="topleft" + left="10" + name="metallic-roughness texture" + tool_tip="GLTF metallic-roughness map with optional occlusion. Red channel is occlusion, green channel is roughness, blue channel is metalness." + top_pad="8" + /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_pad="5" + top_delta="-15" + > + Metallic Factor + </text> + <spinner + decimal_digits="3" + follows="left|top" + height="19" + increment="0.01" + initial_value="0" + layout="topleft" + left_delta="0" + top_pad="5" + max_val="100" + name="metalness factor" + width="64" + /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_delta="0" + top_pad="5" + width="96" + > + Roughness Factor + </text> + <spinner + decimal_digits="3" + follows="left|top" + height="19" + increment="0.01" + initial_value="0" + layout="topleft" + left_delta="0" + top_pad="5" + max_val="100" + name="roughness factor" + width="64" + /> + </panel> + <panel + border="true" + follows="left|top" + width="246" + height="160" + layout="topleft" + left="5" + mouse_opaque="false" + name="Texture" + top_pad="5" + > + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="10" + top="5" + width="64"> + Emissive: + </text> + <texture_picker + can_apply_immediately="true" + default_image_name="Default" + fallback_image="materials_ui_x_24.png" + follows="left|top" + top_pad="8" + height="151" + layout="topleft" + left="10" + name="emissive texture" + width="128" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_pad="5" + top_delta="-15" + > + Tint + </text> + <color_swatch + can_apply_immediately="true" + follows="left|top" + height="40" + label_height="0" + layout="topleft" + left_delta="0" + top_pad="5" + name="emissive color" + width="40" /> + <!--<text + type="string" + length="1" + follows="left|top" + height="10" + width="64" + layout="topleft" + left_delta="0" + top_pad="5" + > + Intensity + </text> + <spinner + decimal_digits="3" + follows="left|top" + height="19" + increment="0.01" + initial_value="0" + layout="topleft" + left_delta="0" + top_pad="5" + max_val="100" + width="64" + />--> + </panel> + <panel + border="true" + follows="left|top" + width="246" + height="160" + layout="topleft" + left="5" + mouse_opaque="false" + top_pad="5" + > + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="10" + top="5" + width="64"> + Normal: + </text> + <texture_picker + can_apply_immediately="true" + default_image_name="Default" + fallback_image="materials_ui_x_24.png" + follows="left|top" + top_pad="8" + height="151" + layout="topleft" + left="10" + name="normal texture" + width="128" /> + <!--<check_box + follows="left|top" + label="Mikkt Space" + left_pad="10" + top_delta="0" + height="25" + width="120" />--> + </panel> + <check_box + follows="left|top" + label="Double Sided" + left="5" + top_pad="5" + name="double sided" + height="25" + width="120" /> + <button + follows="right|bottom" + height="25" + label="Save" + layout="bottomright" + name="save" + tool_tip="Browse for an editor (executable) to edit floater XML files" + top_delta="-2" + left="5" + width="246" /> + +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 78ca170813..60a177f0bd 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -183,6 +183,14 @@ function="Inventory.DoCreate" parameter="gesture" /> </menu_item_call> + <menu_item_call + label="New Material" + layout="topleft" + name="New Material"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="material" /> + </menu_item_call> <menu label="New Clothes" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml index 3385a29a6c..0e193521a3 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml @@ -97,6 +97,14 @@ function="Inventory.DoCreate" parameter="gesture" /> </menu_item_call> + <menu_item_call + label="New Material" + layout="topleft" + name="New Material"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="material" /> + </menu_item_call> <menu height="175" label="New Clothes" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 7a5c2099eb..623d0d88eb 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1595,7 +1595,15 @@ function="World.EnvPreset" parameter="" /> </menu_item_call> </menu> - <menu_item_separator/> + <menu_item_call + label="Material Editor" + name="material_editor_menu_item"> + <menu_item_call.on_click + function="Floater.ToggleOrBringToFront" + parameter="material_editor" /> + </menu_item_call> + + <menu_item_separator/> <menu_item_call enabled="false" label="Undo" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index acb3a720b9..0866f29355 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3835,6 +3835,7 @@ Abuse Report</string> <string name="New Physics">New Physics</string> <string name="Invalid Wearable">Invalid Wearable</string> <string name="New Gesture">New Gesture</string> + <string name="New Material">New Material</string> <string name="New Script">New Script</string> <string name="New Note">New Note</string> <string name="New Folder">New Folder</string> |