*/}}
Kaynağa Gözat

Knob viewer

YimingWu 1 yıl önce
ebeveyn
işleme
0f45a0ef85
4 değiştirilmiş dosya ile 144 ekleme ve 72 silme
  1. 2 2
      la_audio.c
  2. 3 0
      la_interface.h
  3. 9 4
      resources/la_nodes_basic.c
  4. 130 66
      resources/la_widgets.c

+ 2 - 2
la_audio.c

@@ -396,14 +396,14 @@ void laui_EnvelopeNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laCol
     b=laBeginRow(uil,c,0,0); \
     laShowNodeSocket(uil,c,This,"in_" what,0)->Flags|=LA_UI_SOCKET_LABEL_E; \
     b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_" what ".source")));{ \
-    laShowItem(uil,c,This,what)->Expand=1; \
+        laUiItem* value=laShowItem(uil,c,This,what);value->Expand=1; value->Flags|=LA_UI_FLAGS_KNOB;\
     } laEndCondition(uil,b1); \
     laEndRow(uil,b);
 
     ADSR_ROW("attack") ADSR_ROW("delay") ADSR_ROW("sustain") ADSR_ROW("release")
     
     b=laBeginRow(uil,c,0,0);
-    laShowItem(uil,c,This,"in_trigger"); laShowItem(uil,c,This,"trigger")->Flags|=LA_UI_FLAGS_CYCLE;
+    laShowItem(uil,c,This,"in_trigger"); laShowItem(uil,c,This,"trigger")->Flags|=LA_UI_FLAGS_MOMENTARY|LA_UI_FLAGS_HIGHLIGHT;
     laShowSeparator(uil,c)->Expand=1; laShowItem(uil,c,This,"out")->Flags|=LA_UI_SOCKET_LABEL_W;
     laEndRow(uil,b);
 }

+ 3 - 0
la_interface.h

@@ -1113,6 +1113,9 @@ STRUCTURE(laWidget){
 
 #define LA_UI_FLAGS_TERMINAL_INPUT LA_UI_FLAGS_COLOR_SPACE_CLAY
 
+#define LA_UI_FLAGS_MOMENTARY (LA_UI_FLAGS_CYCLE|LA_UI_FLAGS_NODE_CONTAINER)
+#define LA_UI_FLAGS_KNOB LA_UI_FLAGS_NODE_CONTAINER
+
 #define LA_UI_SOCKET_LABEL_N LA_TEXT_ALIGN_LEFT
 #define LA_UI_SOCKET_LABEL_S LA_TEXT_ALIGN_RIGHT
 #define LA_UI_SOCKET_LABEL_W LA_TEXT_ALIGN_CENTER

+ 9 - 4
resources/la_nodes_basic.c

@@ -1063,13 +1063,20 @@ void laui_AddNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *
     laShowItemFull(gu,gc,0,"la.node_categories",LA_WIDGET_COLLECTION_SINGLE,0,laui_NodeCategory,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
 }
 
+laNodeRack* la_NewRackAfter(laRackPage* parent,laNodeRack* rr){
+    laNodeRack* r=memAcquire(sizeof(laNodeRack));
+    strSafeSet(&r->Name,"New Rack");
+    if(rr) lstInsertItemAfter(&parent->Racks,r,rr); else lstPushItem(&parent->Racks, r);
+    r->ParentPage=parent; r->RackType=parent->RackType;
+}
 int OPINV_MoveNodeToRack(laOperator* a, laEvent *e){
     laBaseNode* n=a->This?a->This->EndInstance:0; if(!n||!n->InRack) return LA_CANCELED;
     laBaseNodeType* bnt=0; laNodeRack* target;
 
     char* direction=strGetArgumentString(a->ExtraInstructionsP,"direction");
     
-    if(strSame(direction,"left")) target=n->InRack->Item.pPrev; else target=n->InRack->Item.pNext;
+    if(strSame(direction,"left")){ target=n->InRack->Item.pPrev; if(!target){ target=la_NewRackAfter(n->InRack->ParentPage,0); } }
+    else{ target=n->InRack->Item.pNext; if(!target){ target=la_NewRackAfter(n->InRack->ParentPage,n->InRack->ParentPage->Racks.pLast); } }
     if(!target) return LA_CANCELED;
 
     lstRemoveItem(&n->InRack->Nodes, n); lstAppendItem(&target->Nodes,n); n->InRack=target;
@@ -1100,9 +1107,7 @@ int OPINV_MoveRack(laOperator* a, laEvent *e){
 }
 int OPINV_InsertRack(laOperator* a, laEvent *e){
     laNodeRack* rr=a->This?a->This->EndInstance:0; if(!rr) return LA_CANCELED;
-    laNodeRack* r=memAcquire(sizeof(laNodeRack));
-    strSafeSet(&r->Name,"New Rack");
-    lstInsertItemAfter(&rr->ParentPage->Racks,r,rr); r->ParentPage=rr->ParentPage; r->RackType=rr->RackType;
+    laNodeRack* r = la_NewRackAfter(rr->ParentPage,rr);
     laNotifyInstanceUsers(r->ParentPage); laRecordInstanceDifferences(r->ParentPage,"la_rack_page"); laPushDifferences("Insert Rack", 0);
     return LA_FINISHED;
 }

+ 130 - 66
resources/la_widgets.c

@@ -113,8 +113,9 @@ int la_ArrayGetHeight(laUiItem *ui){
     return laGetArrayLength(&ui->PP);
 }
 int la_ValueGetHeight(laUiItem*ui){
-    if(ui->Flags&LA_UI_FLAGS_TRANSPOSE){ return la_ArrayGetHeight(ui); }
-    return 1;
+    int rows = ui->Extra->HeightCoeff; TNS_CLAMP(rows,1,4);
+    if(ui->Flags&LA_UI_FLAGS_TRANSPOSE){ return la_ArrayGetHeight(ui)*rows; }
+    return rows;
 }
 int la_ValueMeterGetHeight(laUiItem*ui){
     if(ui->Flags&LA_UI_FLAGS_TRANSPOSE){ return ui->Extra->HeightCoeff?ui->Extra->HeightCoeff:6; }
@@ -568,6 +569,7 @@ void la_IntDraw(laUiItem *ui, int h){
     int NoDecal=ui->Flags&LA_UI_FLAGS_NO_DECAL;
     int NoLabel=ui->Flags&LA_UI_FLAGS_NO_LABEL;
     int IsDisabled=ui->Flags&LA_UI_FLAGS_DISABLED;
+    int IsKnob = ui->Flags&LA_UI_FLAGS_NODE_CONTAINER;
 
     if (laIsPropertyReadOnly(&ui->PP) && !NoDecal) ui->State = LA_BT_DISABLED;
 
@@ -602,40 +604,68 @@ void la_IntDraw(laUiItem *ui, int h){
             ui->State = LA_UI_ACTIVE;
         }
 
-        if(!NoDecal){
+        if(IsKnob && !ui->Extra->Edit){
+            real ctrx = (real)(_L+_R)/2.0f, ctry=(real)(_U+_B)/2.0f, radius=(real)(_B-_U)/2.0f;
             tnsUseNoTexture();
+            real verts[52];//24*2+ctr+overlap
+            tnsMakeCircle2d(&verts[2],24,ctrx,ctry,radius,0);
+            tnsVectorCopy2d(&verts[2],&verts[50]);
+            verts[0]=ctrx; verts[1]=ctry;
             tnsColor4dv(laThemeColor(bt,ui->State));
-            tnsVertex2d(_L, _U); tnsVertex2d(_R, _U);
-            tnsVertex2d(_R, _B); tnsVertex2d(_L, _B);
-            tnsPackAs(GL_TRIANGLE_FAN);
-
-            if (Ranged){
-                int L1 = _L;
-                int R1 = (real)(Data[i] - min) / (real)(max - min) * (real)(Seg) + L1;
-                tnsUseNoTexture(); real* color=laThemeColor(bt,LA_BT_TEXT);
-                tnsColor4d(LA_COLOR3(color),0.3);
-                tnsVertex2d(L1, _U); tnsVertex2d(R1, _U);
-                tnsVertex2d(R1, _B); tnsVertex2d(L1, _B);
-                tnsPackAs(GL_TRIANGLE_FAN);
+            tnsVertexArray2d(verts,26); tnsPackAs(GL_TRIANGLE_FAN);
+            tnsMakeCircle2d(verts,24,ctrx,ctry,radius,0);
+            tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
+            tnsVertexArray2d(verts,24); tnsPackAs(GL_LINE_LOOP);
+            if(Ranged){
+                real arc[52];  int arcindex[26]; // 12 slices 13 ends
+                real range = (real)(Data[i] - min) / (real)(max - min) * TNS_PI * 1.5;
+                tnsMakeArc2d(arc,12,ctrx,ctry,radius,TNS_PI*2.75, TNS_PI*2.75 + range);
+                tnsMakeArc2d(&arc[26],12,ctrx,ctry,radius*0.6,TNS_PI*2.75, TNS_PI*2.75 + range);
+                tnsMakeBridgedIndex(arcindex, 13, 0, 0);
+                real *color = laThemeColor(bt,LA_BT_TEXT|ui->State); //tnsColor4d(LA_COLOR3(color),0.3);
+                tnsColor4dv(color);
+                tnsVertexArray2d(arc,26); tnsIndexArray(arcindex,26); tnsPackAs(GL_TRIANGLE_STRIP);
+                tnsMakeArc2d(&arc[2],12,ctrx,ctry,radius*0.6,TNS_PI*2.75, TNS_PI*4.25);
+                tnsVertexArray2d(&arc[2],13);
+                tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
+                tnsPackAs(GL_LINE_STRIP);
             }
+        }else{
+            if(!NoDecal){
+                tnsUseNoTexture();
+                tnsColor4dv(laThemeColor(bt,ui->State));
+                tnsVertex2d(_L, _U); tnsVertex2d(_R, _U);
+                tnsVertex2d(_R, _B); tnsVertex2d(_L, _B);
+                tnsPackAs(GL_TRIANGLE_FAN);
 
-            tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
-            tnsVertex2d(_L, _U); tnsVertex2d(_R, _U);
-            tnsVertex2d(_R, _B); tnsVertex2d(_L, _B);
-            tnsPackAs(GL_LINE_LOOP);
-        }
+                if (Ranged){
+                    int L1 = _L;
+                    int R1 = (real)(Data[i] - min) / (real)(max - min) * (real)(Seg) + L1;
+                    tnsUseNoTexture(); real* color=laThemeColor(bt,LA_BT_TEXT);
+                    tnsColor4d(LA_COLOR3(color),0.3);
+                    tnsVertex2d(L1, _U); tnsVertex2d(R1, _U);
+                    tnsVertex2d(R1, _B); tnsVertex2d(L1, _B);
+                    tnsPackAs(GL_TRIANGLE_FAN);
+                }
 
-        if (ui->Extra->On == i + 1 && ui->Extra->Edit){
-            uint32_t *buf = strGetCursorLine(ui->Extra->Edit, 0)->Buf;
-            int LL = _L + (Seg - tnsStringGetWidthU(buf, 0, ui->Flags&LA_TEXT_MONO)) / 2;
-            tnsColor4dv(laThemeColor(bt, LA_BT_TEXT));
-            la_SingleLineStringDrawSelection(ui, _L, _U, bt, buf, ui->Extra->Edit);
+                tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
+                tnsVertex2d(_L, _U); tnsVertex2d(_R, _U);
+                tnsVertex2d(_R, _B); tnsVertex2d(_L, _B);
+                tnsPackAs(GL_LINE_LOOP);
+            }
+            if (ui->Extra->On == i + 1 && ui->Extra->Edit){
+                uint32_t *buf = strGetCursorLine(ui->Extra->Edit, 0)->Buf;
+                int LL = _L + (Seg - tnsStringGetWidthU(buf, 0, ui->Flags&LA_TEXT_MONO)) / 2;
+                tnsColor4dv(laThemeColor(bt, LA_BT_TEXT));
+                la_SingleLineStringDrawSelection(ui, _L, _U, bt, buf, ui->Extra->Edit);
 
-            tnsDrawStringM(0, buf, laThemeColor(bt, LA_BT_TEXT_ACTIVE), _L + bt->LM, _R - bt->RM, _U, ui->Flags);
-        }else{
-            tnsDrawStringWithPriority(NoLabel?0:buf2, buf,
-                IsDisabled?laThemeColor(bt, LA_BT_DISABLED):laThemeColor(bt, LA_BT_TEXT|ui->State), bt->TextAlign, _L + bt->LM, _R - bt->RM, _U, ui->Flags);//, ui->ExtraInstructions);
+                tnsDrawStringM(0, buf, laThemeColor(bt, LA_BT_TEXT_ACTIVE), _L + bt->LM, _R - bt->RM, _U, ui->Flags);
+            }else{
+                tnsDrawStringWithPriority(NoLabel?0:buf2, buf,
+                    IsDisabled?laThemeColor(bt, LA_BT_DISABLED):laThemeColor(bt, LA_BT_TEXT|ui->State), bt->TextAlign, _L + bt->LM, _R - bt->RM, _U, ui->Flags);//, ui->ExtraInstructions);
+            }
         }
+
         if (ui->Extra && ui->Extra->On == i + 1) ui->State = Original;
     }
 
@@ -657,6 +687,7 @@ void la_FloatDraw(laUiItem *ui, int h){
     int IsRad=ui->PP.LastPs->p->IsRadAngle;
     int NoLabel=ui->Flags&LA_UI_FLAGS_NO_LABEL;
     int IsDisabled=ui->Flags&LA_UI_FLAGS_DISABLED;
+    int IsKnob = ui->Flags&LA_UI_FLAGS_NODE_CONTAINER;
 
     if (laIsPropertyReadOnly(&ui->PP) && !NoDecal) ui->State = LA_BT_DISABLED;
 
@@ -687,39 +718,68 @@ void la_FloatDraw(laUiItem *ui, int h){
             ui->State = LA_UI_ACTIVE;
         }
 
-        if(!NoDecal){
+        if(IsKnob && !ui->Extra->Edit){
+            real ctrx = (real)(_L+_R)/2.0f, ctry=(real)(_U+_B)/2.0f, radius=(real)(_B-_U)/2.0f;
             tnsUseNoTexture();
+            real verts[52];//24*2+ctr+overlap
+            tnsMakeCircle2d(&verts[2],24,ctrx,ctry,radius,0);
+            tnsVectorCopy2d(&verts[2],&verts[50]);
+            verts[0]=ctrx; verts[1]=ctry;
             tnsColor4dv(laThemeColor(bt,ui->State));
-            tnsVertex2d(_L, _U); tnsVertex2d(_R, _U);
-            tnsVertex2d(_R, _B); tnsVertex2d(_L, _B);
-            tnsPackAs(GL_TRIANGLE_FAN);
-
-            if (Ranged){
-                int L1 = _L;
-                int R1 = (real)(Data[i] - min) / (real)(max - min) * (real)(Seg) + L1;
-                tnsUseNoTexture(); real* color=laThemeColor(bt,LA_BT_TEXT);
-                tnsColor4d(LA_COLOR3(color),0.3);
-                tnsVertex2d(L1, _U); tnsVertex2d(R1, _U);
-                tnsVertex2d(R1, _B); tnsVertex2d(L1, _B);
-                tnsPackAs(GL_TRIANGLE_FAN);
+            tnsVertexArray2d(verts,26); tnsPackAs(GL_TRIANGLE_FAN);
+            tnsMakeCircle2d(verts,24,ctrx,ctry,radius,0);
+            tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
+            tnsVertexArray2d(verts,24); tnsPackAs(GL_LINE_LOOP);
+            if(Ranged){
+                real arc[52];  int arcindex[26]; // 12 slices 13 ends
+                real range = (real)(Data[i] - min) / (real)(max - min) * TNS_PI * 1.5;
+                tnsMakeArc2d(arc,12,ctrx,ctry,radius,TNS_PI*2.75, TNS_PI*2.75 + range);
+                tnsMakeArc2d(&arc[26],12,ctrx,ctry,radius*0.6,TNS_PI*2.75, TNS_PI*2.75 + range);
+                tnsMakeBridgedIndex(arcindex, 13, 0, 0);
+                real *color = laThemeColor(bt,LA_BT_TEXT|ui->State); //tnsColor4d(LA_COLOR3(color),0.3);
+                tnsColor4dv(color);
+                tnsVertexArray2d(arc,26); tnsIndexArray(arcindex,26); tnsPackAs(GL_TRIANGLE_STRIP);
+                tnsMakeArc2d(&arc[2],12,ctrx,ctry,radius*0.6,TNS_PI*2.75, TNS_PI*4.25);
+                arc[0] = ctrx + cos(TNS_PI*2.75) * radius; arc[1] = ctry + sin(TNS_PI*2.75) * radius;
+                arc[28] =ctrx + cos(TNS_PI*4.25) * radius; arc[29] =ctry + sin(TNS_PI*4.25) * radius;
+                tnsVertexArray2d(arc,15);
+                tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
+                tnsPackAs(GL_LINE_STRIP);
             }
+        }else{
+            if(!NoDecal){
+                tnsUseNoTexture();
+                tnsColor4dv(laThemeColor(bt,ui->State));
+                tnsVertex2d(_L, _U); tnsVertex2d(_R, _U);
+                tnsVertex2d(_R, _B); tnsVertex2d(_L, _B);
+                tnsPackAs(GL_TRIANGLE_FAN);
 
-            tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
-            tnsVertex2d(_L, _U); tnsVertex2d(_R, _U);
-            tnsVertex2d(_R, _B); tnsVertex2d(_L, _B);
-            tnsPackAs(GL_LINE_LOOP);
-        }
+                if (Ranged){
+                    int L1 = _L;
+                    int R1 = (real)(Data[i] - min) / (real)(max - min) * (real)(Seg) + L1;
+                    tnsUseNoTexture(); real* color=laThemeColor(bt,LA_BT_TEXT);
+                    tnsColor4d(LA_COLOR3(color),0.3);
+                    tnsVertex2d(L1, _U); tnsVertex2d(R1, _U);
+                    tnsVertex2d(R1, _B); tnsVertex2d(L1, _B);
+                    tnsPackAs(GL_TRIANGLE_FAN);
+                }
 
-        if (ui->Extra->On == i + 1 && ui->Extra->Edit){
-            uint32_t *buf = strGetCursorLine(ui->Extra->Edit,0)->Buf;
-            int LL = _L + (Seg - tnsStringGetWidthU(buf, 0, ui->Flags&LA_TEXT_MONO)) / 2;
-            tnsColor4dv(laThemeColor(bt, LA_BT_TEXT));
-            la_SingleLineStringDrawSelection(ui, _L, _U, bt, buf, ui->Extra->Edit);
+                tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
+                tnsVertex2d(_L, _U); tnsVertex2d(_R, _U);
+                tnsVertex2d(_R, _B); tnsVertex2d(_L, _B);
+                tnsPackAs(GL_LINE_LOOP);
+            }
+            if (ui->Extra->On == i + 1 && ui->Extra->Edit){
+                uint32_t *buf = strGetCursorLine(ui->Extra->Edit,0)->Buf;
+                int LL = _L + (Seg - tnsStringGetWidthU(buf, 0, ui->Flags&LA_TEXT_MONO)) / 2;
+                tnsColor4dv(laThemeColor(bt, LA_BT_TEXT));
+                la_SingleLineStringDrawSelection(ui, _L, _U, bt, buf, ui->Extra->Edit);
 
-            tnsDrawStringM(0, buf, laThemeColor(bt, LA_BT_TEXT_ACTIVE), _L + bt->LM, _R - bt->RM, _U, ui->Flags);
-        }else{
-            tnsDrawStringWithPriority(NoLabel?0:buf2, buf,
-                IsDisabled?laThemeColor(bt, LA_BT_DISABLED):laThemeColor(bt, LA_BT_TEXT|ui->State), bt->TextAlign, _L + bt->LM, _R - bt->RM, _U, ui->Flags);//, ui->ExtraInstructions);
+                tnsDrawStringM(0, buf, laThemeColor(bt, LA_BT_TEXT_ACTIVE), _L + bt->LM, _R - bt->RM, _U, ui->Flags);
+            }else{
+                tnsDrawStringWithPriority(NoLabel?0:buf2, buf,
+                    IsDisabled?laThemeColor(bt, LA_BT_DISABLED):laThemeColor(bt, LA_BT_TEXT|ui->State), bt->TextAlign, _L + bt->LM, _R - bt->RM, _U, ui->Flags);//, ui->ExtraInstructions);
+            }
         }
         if (ui->Extra && ui->Extra->On == i + 1) ui->State = Original;
     }
@@ -1957,6 +2017,7 @@ int OPMOD_IntArrayHorizon(laOperator *a, laEvent *e){
     int IsVertical=(ui->Flags&LA_UI_FLAGS_TRANSPOSE)!=0;
     int NoEvent = ui->Flags&LA_UI_FLAGS_NO_EVENT;
     int NoTooltip=ui->Flags&LA_UI_FLAGS_NO_TOOLTIP;
+    int IsKnob = ui->Flags&LA_UI_FLAGS_NODE_CONTAINER;
 
     if (!laIsInUiItem(ui, e->x, e->y) && !ui->Extra->On){
         ui->State = LA_UI_NORMAL;
@@ -1997,12 +2058,12 @@ int OPMOD_IntArrayHorizon(laOperator *a, laEvent *e){
     }
     if (e->Type == LA_MOUSEMOVE && ui->Extra->On){
         if(ui->Extra->Edit){ return LA_RUNNING; }
-        int dist=abs(e->x - uit->LastX);
+        int dist=abs(e->x - uit->LastX + uit->LastY - e->y);
         if (dist > MAIN.ValuatorThreshold || uit->Dragging){
-            int min,max,Ranged = laGetIntRange(&ui->PP, &min, &max); real step=ip->Step; if(Ranged){ step=(real)(max-min)/(ui->R-ui->L); }
+            int min,max,Ranged = laGetIntRange(&ui->PP, &min, &max); real step=ip->Step; if(Ranged&&!IsKnob){ step=(real)(max-min)/(ui->R-ui->L); }
             //laGetIntArray(&ui->PP, &TmpArr);
             //uit->TargetIndexVali = TmpArr[ui->Extra->On - 1];
-            int delta=e->x-uit->LastX; if(!uit->Dragging) delta=delta>0?1:-1;
+            int delta=e->x-uit->LastX; if(IsKnob){ int dy=uit->LastY-e->y; delta=delta+dy; } if(!uit->Dragging) delta=delta>0?1:-1;
             uit->TargetIndexValf +=  delta*step;
             laSetIntArraySingle(&ui->PP, ui->Extra->On - 1, uit->TargetIndexValf);
             uit->LastX = e->x;
@@ -2078,6 +2139,7 @@ int OPMOD_FloatArrayHorizon(laOperator *a, laEvent *e){
     int NoEvent = ui->Flags&LA_UI_FLAGS_NO_EVENT;
     int IsRad=ui->PP.LastPs->p->IsRadAngle;
     int NoTooltip=ui->Flags&LA_UI_FLAGS_NO_TOOLTIP;
+    int IsKnob = ui->Flags&LA_UI_FLAGS_NODE_CONTAINER;
 
     if (!laIsInUiItem(ui, e->x, e->y) && !ui->Extra->On && !NoTooltip){
         ui->State = LA_UI_NORMAL;
@@ -2119,12 +2181,12 @@ int OPMOD_FloatArrayHorizon(laOperator *a, laEvent *e){
     }
     if (e->Type == LA_MOUSEMOVE && ui->Extra->On){
         if(uit->Edit){ return LA_RUNNING; }
-        int dist=abs(e->x - uit->LastX);
+        int dist=abs(e->x - uit->LastX - e->y + uit->LastY);
         if (dist > MAIN.ValuatorThreshold || uit->Dragging){
-            real min,max; int Ranged = laGetFloatRange(&ui->PP, &min, &max); real step=fp->Step; if(Ranged){ step=(max-min)/(ui->R-ui->L); }
+            real min,max; int Ranged = laGetFloatRange(&ui->PP, &min, &max); real step=fp->Step; if(Ranged&&!IsKnob){ step=(max-min)/(ui->R-ui->L); }
             laGetFloatArray(&ui->PP, &TmpArr);
             uit->TargetIndexValf = TmpArr[ui->Extra->On - 1];
-            int delta=e->x-uit->LastX; if(!uit->Dragging) delta=delta>0?1:-1;
+            int delta=e->x-uit->LastX; if(IsKnob){ int dy=uit->LastY-e->y; delta=delta+dy; }  if(!uit->Dragging) delta=delta>0?1:-1;
             uit->TargetIndexValf +=  delta*step;
             laSetFloatArraySingle(&ui->PP, ui->Extra->On - 1, uit->TargetIndexValf);
             uit->LastX = e->x;
@@ -2313,6 +2375,8 @@ int OPMOD_EnumSelector(laOperator *a, laEvent *e){
     laEnumItem *Data[32];
     int NoEvent = ui->Flags&LA_UI_FLAGS_NO_EVENT;
     int NoTooltip=ui->Flags&LA_UI_FLAGS_NO_TOOLTIP;
+    int IsCycle = ui->Flags&LA_UI_FLAGS_CYCLE;
+    int IsMomentary = IsCycle && ui->Flags&LA_UI_FLAGS_NODE_CONTAINER;
     // norm      e1
     // expand    e1 e2 e3
     // expand vertical  (vertical)
@@ -2328,9 +2392,9 @@ int OPMOD_EnumSelector(laOperator *a, laEvent *e){
         return LA_RUNNING;
     }
 
-    if (!laIsInUiItem(ui, e->x, e->y)){ return LA_FINISHED_PASS; }
+    if (!laIsInUiItem(ui, e->x, e->y) && !uit->On){ return LA_FINISHED_PASS; }
     
-    if (e->Type == LA_TIME_IDLE && !NoTooltip){
+    if (e->Type == LA_TIME_IDLE && !NoTooltip && !uit->On){
         int GX = e->x, GY = e->y; laLocalToWindow(a, a->ToPanel, &GX, &GY);
         laPanel *p = laEnableIdlePanel(a->ToPanel, a, 0, 0, &ui->PP, GX, GX + 150, GY, 600, 200, e);
         return LA_RUNNING;
@@ -2338,12 +2402,11 @@ int OPMOD_EnumSelector(laOperator *a, laEvent *e){
 
     if(NoEvent){ return LA_RUNNING_PASS; }
 
-    if (e->Type == LA_L_MOUSE_DOWN){
+    if (e->Type == LA_L_MOUSE_DOWN || (IsMomentary && e->Type == LA_L_MOUSE_UP)){
         if (laIsPropertyReadOnly(&ui->PP)) return LA_RUNNING_PASS;
 
         int IsVertical = ui->Flags&LA_UI_FLAGS_TRANSPOSE;
         int IsExpand = ui->Flags&LA_UI_FLAGS_EXPAND;
-        int IsCycle = ui->Flags&LA_UI_FLAGS_CYCLE;
         int ArrLen = laGetArrayLength(&ui->PP);
         if(ArrLen==1){ if(!IsExpand) IsVertical=0; }else{ IsExpand=1; }
         int EnumLen = (IsExpand&&(!IsCycle)) ? laGetEnumEntryLen(&ui->PP) : 1;
@@ -2377,6 +2440,7 @@ int OPMOD_EnumSelector(laOperator *a, laEvent *e){
             laEnumItem* ei=laGetEnumArrayIndexed(&ui->PP, ArrTarget);
             if(!ei){ ei=((laEnumProp*)ui->PP.LastPs->p)->Items.pFirst; }
             ei = ei->Item.pNext?ei->Item.pNext:((laEnumProp*)ui->PP.LastPs->p)->Items.pFirst;
+            if(IsMomentary){  uit->On = 1; if(e->Type==LA_L_MOUSE_UP){ ei = ei=((laEnumProp*)ui->PP.LastPs->p)->Items.pFirst; uit->On = 0;} }
             laSetEnumArrayIndexed(&ui->PP, ArrTarget, ei->Index);
             laConfirmInt(a,EnumTarget,LA_CONFIRM_DATA);
             laRecordAndPushProp(&ui->PP,0); laMarkPropChanged(&ui->PP);