viewer#1131 gltf model upload UI WIP #3
parent
e75595a1c1
commit
279ec534dd
|
|
@ -31,7 +31,9 @@
|
|||
|
||||
#include "gltf/asset.h"
|
||||
#include "llcallbacklist.h"
|
||||
#include "llmenubutton.h"
|
||||
#include "llselectmgr.h"
|
||||
#include "llspinctrl.h"
|
||||
#include "llviewerobject.h"
|
||||
|
||||
const LLColor4U DEFAULT_WHITE(255, 255, 255);
|
||||
|
|
@ -43,16 +45,69 @@ LLFloaterGLTFAssetEditor::LLFloaterGLTFAssetEditor(const LLSD& key)
|
|||
, mUIColor(LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE))
|
||||
{
|
||||
setTitle("GLTF Asset Editor (WIP)");
|
||||
|
||||
mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", [this](LLUICtrl* ctrl, const LLSD& data) { onMenuDoToSelected(data); });
|
||||
mEnableCallbackRegistrar.add("PanelObject.menuEnable", [this](LLUICtrl* ctrl, const LLSD& data) { return onMenuEnableItem(data); });
|
||||
}
|
||||
|
||||
LLFloaterGLTFAssetEditor::~LLFloaterGLTFAssetEditor()
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(idle, this);
|
||||
|
||||
if (mScroller)
|
||||
{
|
||||
removeChild(mScroller);
|
||||
delete mScroller;
|
||||
mScroller = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFloaterGLTFAssetEditor::postBuild()
|
||||
{
|
||||
mItemListPanel = getChild<LLPanel>("item_list_panel");
|
||||
// Position
|
||||
mMenuClipboardPos = getChild<LLMenuButton>("clipboard_pos_btn");
|
||||
mCtrlPosX = getChild<LLSpinCtrl>("Pos X", true);
|
||||
mCtrlPosX->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
|
||||
mCtrlPosY = getChild<LLSpinCtrl>("Pos Y", true);
|
||||
mCtrlPosY->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
|
||||
mCtrlPosZ = getChild<LLSpinCtrl>("Pos Z", true);
|
||||
mCtrlPosZ->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
|
||||
|
||||
// Scale
|
||||
mMenuClipboardScale = getChild<LLMenuButton>("clipboard_size_btn");
|
||||
mCtrlScaleX = getChild<LLSpinCtrl>("Scale X", true);
|
||||
mCtrlScaleX->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
|
||||
mCtrlScaleY = getChild<LLSpinCtrl>("Scale Y", true);
|
||||
mCtrlScaleY->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
|
||||
mCtrlScaleZ = getChild<LLSpinCtrl>("Scale Z", true);
|
||||
mCtrlScaleZ->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
|
||||
|
||||
// Rotation
|
||||
mMenuClipboardRot = getChild<LLMenuButton>("clipboard_rot_btn");
|
||||
mCtrlRotX = getChild<LLSpinCtrl>("Rot X", true);
|
||||
mCtrlRotX->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
|
||||
mCtrlRotY = getChild<LLSpinCtrl>("Rot Y", true);
|
||||
mCtrlRotY->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
|
||||
mCtrlRotZ = getChild<LLSpinCtrl>("Rot Z", true);
|
||||
mCtrlPosZ->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
|
||||
setTransformsEnabled(false);
|
||||
// todo: do multiple panels based on selected element.
|
||||
mTransformsPanel = getChild<LLPanel>("transform_panel", true);
|
||||
mTransformsPanel->setVisible(false);
|
||||
|
||||
mItemListPanel = getChild<LLPanel>("item_list_panel", true);
|
||||
initFolderRoot();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLFloaterGLTFAssetEditor::initFolderRoot()
|
||||
{
|
||||
if (mScroller || mFolderRoot)
|
||||
{
|
||||
LL_ERRS() << "Folder root already initialized" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLRect scroller_view_rect = mItemListPanel->getRect();
|
||||
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
|
||||
|
|
@ -87,11 +142,10 @@ bool LLFloaterGLTFAssetEditor::postBuild()
|
|||
mFolderRoot->setScrollContainer(mScroller);
|
||||
mFolderRoot->setFollowsAll();
|
||||
mFolderRoot->setOpen(true);
|
||||
mFolderRoot->setSelectCallback([this](const std::deque<LLFolderViewItem*>& items, bool user_action) { onFolderSelectionChanged(items, user_action); });
|
||||
mScroller->setVisible(true);
|
||||
|
||||
gIdleCallbacks.addFunction(idle, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLFloaterGLTFAssetEditor::onOpen(const LLSD& key)
|
||||
|
|
@ -252,3 +306,212 @@ void LLFloaterGLTFAssetEditor::loadFromSelection()
|
|||
mFolderRoot->update();
|
||||
}
|
||||
|
||||
void LLFloaterGLTFAssetEditor::onFolderSelectionChanged(const std::deque<LLFolderViewItem*>& items, bool user_action)
|
||||
{
|
||||
if (items.empty())
|
||||
{
|
||||
setTransformsEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
LLFolderViewItem* item = items.front();
|
||||
LLGLTFFolderItem* vmi = static_cast<LLGLTFFolderItem*>(item->getViewModelItem());
|
||||
|
||||
switch (vmi->getType())
|
||||
{
|
||||
case LLGLTFFolderItem::TYPE_NODE:
|
||||
{
|
||||
setTransformsEnabled(true);
|
||||
loadNodeTransforms(vmi->getItemId());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
setTransformsEnabled(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterGLTFAssetEditor::setTransformsEnabled(bool val)
|
||||
{
|
||||
mMenuClipboardPos->setEnabled(val);
|
||||
mCtrlPosX->setEnabled(val);
|
||||
mCtrlPosY->setEnabled(val);
|
||||
mCtrlPosZ->setEnabled(val);
|
||||
mMenuClipboardScale->setEnabled(val);
|
||||
mCtrlScaleX->setEnabled(val);
|
||||
mCtrlScaleY->setEnabled(val);
|
||||
mCtrlScaleZ->setEnabled(val);
|
||||
mMenuClipboardRot->setEnabled(val);
|
||||
mCtrlRotX->setEnabled(val);
|
||||
mCtrlRotY->setEnabled(val);
|
||||
mCtrlRotZ->setEnabled(val);
|
||||
}
|
||||
|
||||
void LLFloaterGLTFAssetEditor::loadNodeTransforms(S32 node_id)
|
||||
{
|
||||
if (node_id < 0 || node_id >= mAsset->mNodes.size())
|
||||
{
|
||||
LL_ERRS() << "Node id out of range: " << node_id << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LL::GLTF::Node& node = mAsset->mNodes[node_id];
|
||||
|
||||
mCtrlPosX->set(node.mTranslation[0]);
|
||||
mCtrlPosY->set(node.mTranslation[1]);
|
||||
mCtrlPosZ->set(node.mTranslation[2]);
|
||||
|
||||
mCtrlScaleX->set(node.mScale[0]);
|
||||
mCtrlScaleY->set(node.mScale[1]);
|
||||
mCtrlScaleZ->set(node.mScale[2]);
|
||||
|
||||
LLQuaternion object_rot = LLQuaternion(node.mRotation[0], node.mRotation[1], node.mRotation[2], node.mRotation[3]);
|
||||
object_rot.getEulerAngles(&(mLastEulerDegrees.mV[VX]), &(mLastEulerDegrees.mV[VY]), &(mLastEulerDegrees.mV[VZ]));
|
||||
mLastEulerDegrees *= RAD_TO_DEG;
|
||||
mLastEulerDegrees.mV[VX] = fmod(ll_round(mLastEulerDegrees.mV[VX], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
|
||||
mLastEulerDegrees.mV[VY] = fmod(ll_round(mLastEulerDegrees.mV[VY], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
|
||||
mLastEulerDegrees.mV[VZ] = fmod(ll_round(mLastEulerDegrees.mV[VZ], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
|
||||
|
||||
mCtrlRotX->set(mLastEulerDegrees.mV[VX]);
|
||||
mCtrlRotY->set(mLastEulerDegrees.mV[VY]);
|
||||
mCtrlRotZ->set(mLastEulerDegrees.mV[VZ]);
|
||||
}
|
||||
|
||||
void LLFloaterGLTFAssetEditor::onCommitTransform()
|
||||
{
|
||||
if (!mFolderRoot)
|
||||
{
|
||||
LL_ERRS() << "Folder root not initialized" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLFolderViewItem* item = mFolderRoot->getCurSelectedItem();
|
||||
if (!item)
|
||||
{
|
||||
LL_ERRS() << "Nothing selected" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLGLTFFolderItem* vmi = static_cast<LLGLTFFolderItem*>(item->getViewModelItem());
|
||||
|
||||
if (!vmi || vmi->getType() != LLGLTFFolderItem::TYPE_NODE)
|
||||
{
|
||||
LL_ERRS() << "Only nodes implemented" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
S32 node_id = vmi->getItemId();
|
||||
LL::GLTF::Node& node = mAsset->mNodes[node_id];
|
||||
|
||||
LL::GLTF::vec3 tr(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
|
||||
node.setTranslation(tr);
|
||||
|
||||
LL::GLTF::vec3 scale(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get());
|
||||
node.setScale(scale);
|
||||
|
||||
LLVector3 new_rot(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get());
|
||||
new_rot.mV[VX] = ll_round(new_rot.mV[VX], OBJECT_ROTATION_PRECISION);
|
||||
new_rot.mV[VY] = ll_round(new_rot.mV[VY], OBJECT_ROTATION_PRECISION);
|
||||
new_rot.mV[VZ] = ll_round(new_rot.mV[VZ], OBJECT_ROTATION_PRECISION);
|
||||
|
||||
// Note: must compare before conversion to radians, some value can go 'around' 360
|
||||
LLVector3 delta = new_rot - mLastEulerDegrees;
|
||||
|
||||
if (delta.magVec() >= 0.0005f)
|
||||
{
|
||||
mLastEulerDegrees = new_rot;
|
||||
new_rot *= DEG_TO_RAD;
|
||||
|
||||
LLQuaternion rotation;
|
||||
rotation.setQuat(new_rot.mV[VX], new_rot.mV[VY], new_rot.mV[VZ]);
|
||||
LL::GLTF::quat q;
|
||||
q[0] = rotation.mQ[VX];
|
||||
q[1] = rotation.mQ[VY];
|
||||
q[2] = rotation.mQ[VZ];
|
||||
q[3] = rotation.mQ[VW];
|
||||
|
||||
node.setRotation(q);
|
||||
}
|
||||
|
||||
mAsset->updateTransforms();
|
||||
}
|
||||
|
||||
void LLFloaterGLTFAssetEditor::onMenuDoToSelected(const LLSD& userdata)
|
||||
{
|
||||
std::string command = userdata.asString();
|
||||
|
||||
if (command == "psr_paste")
|
||||
{
|
||||
// todo: implement
|
||||
// onPastePos();
|
||||
// onPasteSize();
|
||||
// onPasteRot();
|
||||
}
|
||||
else if (command == "pos_paste")
|
||||
{
|
||||
// todo: implement
|
||||
}
|
||||
else if (command == "size_paste")
|
||||
{
|
||||
// todo: implement
|
||||
}
|
||||
else if (command == "rot_paste")
|
||||
{
|
||||
// todo: implement
|
||||
}
|
||||
else if (command == "psr_copy")
|
||||
{
|
||||
// onCopyPos();
|
||||
// onCopySize();
|
||||
// onCopyRot();
|
||||
}
|
||||
else if (command == "pos_copy")
|
||||
{
|
||||
// todo: implement
|
||||
}
|
||||
else if (command == "size_copy")
|
||||
{
|
||||
// todo: implement
|
||||
}
|
||||
else if (command == "rot_copy")
|
||||
{
|
||||
// todo: implement
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFloaterGLTFAssetEditor::onMenuEnableItem(const LLSD& userdata)
|
||||
{
|
||||
if (!mFolderRoot)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LLFolderViewItem* item = mFolderRoot->getCurSelectedItem();
|
||||
if (!item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LLGLTFFolderItem* vmi = static_cast<LLGLTFFolderItem*>(item->getViewModelItem());
|
||||
|
||||
if (!vmi || vmi->getType() != LLGLTFFolderItem::TYPE_NODE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string command = userdata.asString();
|
||||
if (command == "pos_paste" || command == "size_paste" || command == "rot_paste")
|
||||
{
|
||||
// todo: implement
|
||||
return true;
|
||||
}
|
||||
if (command == "psr_copy")
|
||||
{
|
||||
// todo: implement
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ namespace LL
|
|||
}
|
||||
}
|
||||
|
||||
class LLSpinCtrl;
|
||||
class LLMenuButton;
|
||||
|
||||
class LLFloaterGLTFAssetEditor : public LLFloater
|
||||
{
|
||||
public:
|
||||
|
|
@ -48,6 +51,7 @@ public:
|
|||
|
||||
bool postBuild() override;
|
||||
void onOpen(const LLSD& key) override;
|
||||
void initFolderRoot();
|
||||
|
||||
LLGLTFViewModel& getRootViewModel() { return mGLTFViewModel; }
|
||||
|
||||
|
|
@ -56,14 +60,42 @@ public:
|
|||
void loadFromNode(S32 node, LLFolderViewFolder* parent);
|
||||
void loadFromSelection();
|
||||
|
||||
private:
|
||||
LLGLTFViewModel mGLTFViewModel;
|
||||
LLUIColor mUIColor;
|
||||
protected:
|
||||
void onFolderSelectionChanged(const std::deque<LLFolderViewItem*>& items, bool user_action);
|
||||
void onCommitTransform();
|
||||
void onMenuDoToSelected(const LLSD& userdata);
|
||||
bool onMenuEnableItem(const LLSD& userdata);
|
||||
|
||||
void setTransformsEnabled(bool val);
|
||||
void loadNodeTransforms(S32 id);
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<LL::GLTF::Asset> mAsset;
|
||||
|
||||
// Folder view related
|
||||
LLUIColor mUIColor;
|
||||
LLGLTFViewModel mGLTFViewModel;
|
||||
LLPanel* mItemListPanel = nullptr;
|
||||
LLFolderView* mFolderRoot = nullptr;
|
||||
LLScrollContainer* mScroller = nullptr;
|
||||
std::shared_ptr<LL::GLTF::Asset> mAsset;
|
||||
|
||||
// Transforms panel
|
||||
LLVector3 mLastEulerDegrees;
|
||||
|
||||
LLPanel* mTransformsPanel = nullptr;
|
||||
LLMenuButton* mMenuClipboardPos = nullptr;
|
||||
LLSpinCtrl* mCtrlPosX = nullptr;
|
||||
LLSpinCtrl* mCtrlPosY = nullptr;
|
||||
LLSpinCtrl* mCtrlPosZ = nullptr;
|
||||
LLMenuButton* mMenuClipboardScale = nullptr;
|
||||
LLSpinCtrl* mCtrlScaleX = nullptr;
|
||||
LLSpinCtrl* mCtrlScaleY = nullptr;
|
||||
LLSpinCtrl* mCtrlScaleZ = nullptr;
|
||||
LLMenuButton* mMenuClipboardRot = nullptr;
|
||||
LLSpinCtrl* mCtrlRotX = nullptr;
|
||||
LLSpinCtrl* mCtrlRotY = nullptr;
|
||||
LLSpinCtrl* mCtrlRotZ = nullptr;
|
||||
};
|
||||
|
||||
#endif LL_LLFLOATERGLTFASSETEDITOR_H
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
bool filter(LLFolderViewFilter& filter) override;
|
||||
|
||||
EType getType() const { return mItemType; }
|
||||
S32 getId() const { return mItemId; }
|
||||
S32 getItemId() const { return mItemId; }
|
||||
|
||||
private:
|
||||
LLUIImagePtr pIcon;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
legacy_header_height="18"
|
||||
can_resize="true"
|
||||
default_tab_group="1"
|
||||
height="400"
|
||||
height="530"
|
||||
width="256"
|
||||
min_height="200"
|
||||
min_height="400"
|
||||
min_width="200"
|
||||
layout="topleft"
|
||||
name="gltf asset editor"
|
||||
|
|
@ -14,13 +14,270 @@
|
|||
<floater.string name="node_tittle" value="Node"/>
|
||||
<floater.string name="mesh_tittle" value="Mesh"/>
|
||||
<floater.string name="skin_tittle" value="Skin"/>
|
||||
<panel
|
||||
|
||||
<layout_stack
|
||||
name="main_layout"
|
||||
orientation="vertical"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="item_list_panel"
|
||||
visible="true"
|
||||
bottom="-1"
|
||||
top="16"
|
||||
left="5"
|
||||
right="-1"/>
|
||||
right="-1"
|
||||
border_size="0">
|
||||
|
||||
<layout_panel
|
||||
name="top_lp"
|
||||
border="true"
|
||||
bevel_style="in"
|
||||
auto_resize="false"
|
||||
user_resize="true"
|
||||
visible="true"
|
||||
height="200">
|
||||
<panel
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="item_list_panel"
|
||||
visible="true"
|
||||
bottom="-1"
|
||||
top="16"
|
||||
left="5"
|
||||
right="-1"/>
|
||||
</layout_panel>
|
||||
|
||||
<layout_panel
|
||||
name="transforms_panel"
|
||||
border="true"
|
||||
bevel_style="in"
|
||||
auto_resize="true"
|
||||
user_resize="true"
|
||||
visible="true"
|
||||
height="150">
|
||||
<menu_button
|
||||
menu_filename="menu_copy_paste_pos.xml"
|
||||
follows="top|left"
|
||||
height="11"
|
||||
image_disabled="ClipboardSmallMenu_Disabled"
|
||||
image_selected="ClipboardSmallMenu_Press"
|
||||
image_unselected="ClipboardSmallMenu_Off"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
top_pad="13"
|
||||
name="clipboard_pos_btn"
|
||||
tool_tip="Paste options"
|
||||
width="19"/>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="10"
|
||||
layout="topleft"
|
||||
name="label position"
|
||||
tool_tip="Position (meters)"
|
||||
left_pad="8"
|
||||
top_delta="0"
|
||||
width="121">
|
||||
Position (m)
|
||||
</text>
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
increment="0.01"
|
||||
initial_value="0"
|
||||
label="X"
|
||||
label_width="10"
|
||||
layout="topleft"
|
||||
left_delta="-27"
|
||||
max_val="512"
|
||||
min_val="-256"
|
||||
name="Pos X"
|
||||
text_enabled_color="1 0 0.3 .7"
|
||||
top_pad="8"
|
||||
width="87" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
increment="0.01"
|
||||
initial_value="0"
|
||||
label="Y"
|
||||
label_width="10"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
max_val="512"
|
||||
min_val="-256"
|
||||
name="Pos Y"
|
||||
text_enabled_color="EmphasisColor"
|
||||
top_pad="3"
|
||||
width="87" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
increment="0.01"
|
||||
initial_value="0"
|
||||
label="Z"
|
||||
label_width="10"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
max_val="4096"
|
||||
min_val="-32"
|
||||
name="Pos Z"
|
||||
text_enabled_color="0 0.8 1 .65"
|
||||
top_pad="3"
|
||||
width="87" />
|
||||
<menu_button
|
||||
menu_filename="menu_copy_paste_size.xml"
|
||||
follows="top|left"
|
||||
height="11"
|
||||
image_disabled="ClipboardSmallMenu_Disabled"
|
||||
image_selected="ClipboardSmallMenu_Press"
|
||||
image_unselected="ClipboardSmallMenu_Off"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
top_pad="13"
|
||||
name="clipboard_size_btn"
|
||||
tool_tip="Paste options"
|
||||
width="19"/>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="10"
|
||||
layout="topleft"
|
||||
left_pad="8"
|
||||
top_delta="0"
|
||||
name="label size"
|
||||
tool_tip="Size (meters)"
|
||||
width="121">
|
||||
Size (m)
|
||||
</text>
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
increment="0.01"
|
||||
initial_value="0"
|
||||
label="X"
|
||||
label_width="10"
|
||||
layout="topleft"
|
||||
left_delta="-27"
|
||||
max_val="64"
|
||||
min_val="0.01"
|
||||
name="Scale X"
|
||||
text_enabled_color="1 1 1 1"
|
||||
top_pad="8"
|
||||
width="87" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
increment="0.01"
|
||||
initial_value="0"
|
||||
label="Y"
|
||||
label_width="10"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
max_val="64"
|
||||
min_val="0.01"
|
||||
name="Scale Y"
|
||||
text_enabled_color="1 1 1 1"
|
||||
top_pad="3"
|
||||
width="87" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
increment="0.01"
|
||||
initial_value="0"
|
||||
label="Z"
|
||||
label_width="10"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
max_val="64"
|
||||
min_val="0.01"
|
||||
name="Scale Z"
|
||||
text_enabled_color="1 1 1 1"
|
||||
top_pad="3"
|
||||
width="87" />
|
||||
<menu_button
|
||||
menu_filename="menu_copy_paste_rot.xml"
|
||||
follows="top|left"
|
||||
height="11"
|
||||
image_disabled="ClipboardSmallMenu_Disabled"
|
||||
image_selected="ClipboardSmallMenu_Press"
|
||||
image_unselected="ClipboardSmallMenu_Off"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
top_pad="13"
|
||||
name="clipboard_rot_btn"
|
||||
tool_tip="Paste options"
|
||||
width="19"/>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="10"
|
||||
layout="topleft"
|
||||
left_pad="8"
|
||||
top_delta="0"
|
||||
name="label rotation"
|
||||
tool_tip="Rotation (degrees)"
|
||||
width="121">
|
||||
Rotation (°)
|
||||
</text>
|
||||
<spinner
|
||||
decimal_digits="2"
|
||||
follows="left|top"
|
||||
height="19"
|
||||
increment="1"
|
||||
initial_value="0"
|
||||
label="X"
|
||||
label_width="10"
|
||||
layout="topleft"
|
||||
left_delta="-27"
|
||||
max_val="9999"
|
||||
min_val="-9999"
|
||||
name="Rot X"
|
||||
text_enabled_color="1 1 1 1"
|
||||
top_pad="8"
|
||||
width="87" />
|
||||
<spinner
|
||||
decimal_digits="2"
|
||||
follows="left|top"
|
||||
height="19"
|
||||
increment="1"
|
||||
initial_value="0"
|
||||
label="Y"
|
||||
label_width="10"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
max_val="9999"
|
||||
min_val="-9999"
|
||||
name="Rot Y"
|
||||
text_enabled_color="1 1 1 1"
|
||||
top_pad="3"
|
||||
width="87" />
|
||||
<spinner
|
||||
decimal_digits="2"
|
||||
follows="left|top"
|
||||
height="19"
|
||||
increment="1"
|
||||
initial_value="0"
|
||||
label="Z"
|
||||
label_width="10"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
max_val="9999"
|
||||
min_val="-9999"
|
||||
name="Rot Z"
|
||||
text_enabled_color="1 1 1 1"
|
||||
top_pad="3"
|
||||
width="87" />
|
||||
</layout_panel>
|
||||
|
||||
<layout_panel
|
||||
name="blank_panel"
|
||||
border="true"
|
||||
bevel_style="in"
|
||||
auto_resize="true"
|
||||
user_resize="true"
|
||||
visible="false"
|
||||
height="150">
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</floater>
|
||||
|
|
|
|||
Loading…
Reference in New Issue