+++ /dev/null
-#ifdef INTERFACE
-CLASS(Animation) EXTENDS(Object)
- METHOD(Animation, configureAnimation, void(entity, entity, void(entity, float), float, float, float, float))
- METHOD(Animation, setTimeStartEnd, void(entity, float, float))
- METHOD(Animation, setTimeStartDuration, void(entity, float, float))
- METHOD(Animation, setValueStartEnd, void(entity, float, float))
- METHOD(Animation, setValueStartDelta, void(entity, float, float))
- METHOD(Animation, setObjectSetter, void(entity, entity, void(entity, float)))
- METHOD(Animation, tick, void(entity, float))
- METHOD(Animation, calcValue, float(entity, float, float, float, float))
- METHOD(Animation, isStopped, float(entity))
- METHOD(Animation, stopAnim, void(entity))
- METHOD(Animation, resumeAnim, void(entity))
- METHOD(Animation, isFinished, float(entity))
- METHOD(Animation, finishAnim, void(entity))
- ATTRIB(Animation, object, entity, NULL)
- ATTRIB(Animation, setter, void(entity, float), setterDummy)
- ATTRIB(Animation, value, float, 0)
- ATTRIB(Animation, startTime, float, 0)
- ATTRIB(Animation, duration, float, 0)
- ATTRIB(Animation, startValue, float, 0)
- ATTRIB(Animation, delta, float, 0)
- ATTRIB(Animation, stopped, float, FALSE)
- ATTRIB(Animation, finished, float, FALSE)
-ENDCLASS(Animation)
-void setterDummy(entity, float);
-#endif
-
-#ifdef IMPLEMENTATION
-void Animation_configureAnimation(entity me, entity obj, void(entity, float) objSetter, float animStartTime, float animDuration, float animStartValue, float animEndValue)
-{
- me.setObjectSetter(me, obj, objSetter);
- me.setTimeStartDuration(me, animStartTime, animDuration);
- me.setValueStartEnd(me, animStartValue, animEndValue);
-}
-
-void Animation_setTimeStartEnd(entity me, float s, float e)
-{
- me.startTime = s;
- me.duration = e - s;
-}
-
-void Animation_setTimeStartDuration(entity me, float s, float d)
-{
- me.startTime = s;
- me.duration = d;
-}
-
-void Animation_setValueStartEnd(entity me, float s, float e)
-{
- me.startValue = s;
- me.delta = e - s;
-}
-
-void Animation_setValueStartDelta(entity me, float s, float d)
-{
- me.startValue = s;
- me.delta = d;
-}
-
-void Animation_setObjectSetter(entity me, entity o, void(entity, float) s)
-{
- me.object = o;
- me.setter = s;
-}
-
-void Animation_tick(entity me, float tickTime)
-{
- if (me.isStopped(me) || me.isFinished(me) || (tickTime < me.startTime))
- return;
-
- if (tickTime >= (me.startTime + me.duration))
- me.finishAnim(me);
- else
- me.value = me.calcValue(me, (tickTime - me.startTime), me.duration, me.startValue, me.delta);
-
- me.setter(me.object, me.value);
-}
-
-float Animation_calcValue(entity me, float tickTime, float animDuration, float animStartValue, float animDelta)
-{
- return animStartValue;
-}
-
-float Animation_isStopped(entity me)
-{
- return me.stopped;
-}
-
-void Animation_stopAnim(entity me)
-{
- me.stopped = TRUE;
-}
-
-void Animation_resumeAnim(entity me)
-{
- me.stopped = FALSE;
-}
-
-float Animation_isFinished(entity me)
-{
- return me.finished;
-}
-
-void Animation_finishAnim(entity me)
-{
- me.value = me.delta + me.startValue;
- me.finished = TRUE;
- me.setter(me.object, me.value);
-}
-
-void setterDummy(entity obj, float objValue)
-{
-}
-
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(Animation) EXTENDS(Object)
+ METHOD(Animation, configureAnimation, void(entity, entity, void(entity, float), float, float, float, float))
+ METHOD(Animation, setTimeStartEnd, void(entity, float, float))
+ METHOD(Animation, setTimeStartDuration, void(entity, float, float))
+ METHOD(Animation, setValueStartEnd, void(entity, float, float))
+ METHOD(Animation, setValueStartDelta, void(entity, float, float))
+ METHOD(Animation, setObjectSetter, void(entity, entity, void(entity, float)))
+ METHOD(Animation, tick, void(entity, float))
+ METHOD(Animation, calcValue, float(entity, float, float, float, float))
+ METHOD(Animation, isStopped, float(entity))
+ METHOD(Animation, stopAnim, void(entity))
+ METHOD(Animation, resumeAnim, void(entity))
+ METHOD(Animation, isFinished, float(entity))
+ METHOD(Animation, finishAnim, void(entity))
+ ATTRIB(Animation, object, entity, NULL)
+ ATTRIB(Animation, setter, void(entity, float), setterDummy)
+ ATTRIB(Animation, value, float, 0)
+ ATTRIB(Animation, startTime, float, 0)
+ ATTRIB(Animation, duration, float, 0)
+ ATTRIB(Animation, startValue, float, 0)
+ ATTRIB(Animation, delta, float, 0)
+ ATTRIB(Animation, stopped, float, FALSE)
+ ATTRIB(Animation, finished, float, FALSE)
+ENDCLASS(Animation)
+void setterDummy(entity, float);
+#endif
+
+#ifdef IMPLEMENTATION
+void Animation_configureAnimation(entity me, entity obj, void(entity, float) objSetter, float animStartTime, float animDuration, float animStartValue, float animEndValue)
+{
+ me.setObjectSetter(me, obj, objSetter);
+ me.setTimeStartDuration(me, animStartTime, animDuration);
+ me.setValueStartEnd(me, animStartValue, animEndValue);
+}
+
+void Animation_setTimeStartEnd(entity me, float s, float e)
+{
+ me.startTime = s;
+ me.duration = e - s;
+}
+
+void Animation_setTimeStartDuration(entity me, float s, float d)
+{
+ me.startTime = s;
+ me.duration = d;
+}
+
+void Animation_setValueStartEnd(entity me, float s, float e)
+{
+ me.startValue = s;
+ me.delta = e - s;
+}
+
+void Animation_setValueStartDelta(entity me, float s, float d)
+{
+ me.startValue = s;
+ me.delta = d;
+}
+
+void Animation_setObjectSetter(entity me, entity o, void(entity, float) s)
+{
+ me.object = o;
+ me.setter = s;
+}
+
+void Animation_tick(entity me, float tickTime)
+{
+ if (me.isStopped(me) || me.isFinished(me) || (tickTime < me.startTime))
+ return;
+
+ if (tickTime >= (me.startTime + me.duration))
+ me.finishAnim(me);
+ else
+ me.value = me.calcValue(me, (tickTime - me.startTime), me.duration, me.startValue, me.delta);
+
+ me.setter(me.object, me.value);
+}
+
+float Animation_calcValue(entity me, float tickTime, float animDuration, float animStartValue, float animDelta)
+{
+ return animStartValue;
+}
+
+float Animation_isStopped(entity me)
+{
+ return me.stopped;
+}
+
+void Animation_stopAnim(entity me)
+{
+ me.stopped = TRUE;
+}
+
+void Animation_resumeAnim(entity me)
+{
+ me.stopped = FALSE;
+}
+
+float Animation_isFinished(entity me)
+{
+ return me.finished;
+}
+
+void Animation_finishAnim(entity me)
+{
+ me.value = me.delta + me.startValue;
+ me.finished = TRUE;
+ me.setter(me.object, me.value);
+}
+
+void setterDummy(entity obj, float objValue)
+{
+}
+
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(AnimHost) EXTENDS(Object)
- METHOD(AnimHost, addAnim, void(entity, entity))
- METHOD(AnimHost, removeAnim, void(entity, entity))
- METHOD(AnimHost, removeAllAnim, void(entity))
- METHOD(AnimHost, removeObjAnim, void(entity, entity))
- METHOD(AnimHost, stopAllAnim, void(entity))
- METHOD(AnimHost, stopObjAnim, void(entity, entity))
- METHOD(AnimHost, resumeAllAnim, void(entity))
- METHOD(AnimHost, resumeObjAnim, void(entity, entity))
- METHOD(AnimHost, finishAllAnim, void(entity))
- METHOD(AnimHost, finishObjAnim, void(entity, entity))
- METHOD(AnimHost, tickAll, void(entity))
- ATTRIB(AnimHost, firstChild, entity, NULL)
- ATTRIB(AnimHost, lastChild, entity, NULL)
-ENDCLASS(AnimHost)
-.entity nextSibling;
-.entity prevSibling;
-#endif
-
-#ifdef IMPLEMENTATION
-void AnimHost_addAnim(entity me, entity other)
-{
- if(other.parent)
- error("Can't add already added anim!");
-
- if(other.isFinished(other))
- error("Can't add finished anim!");
-
- other.parent = me;
-
- entity l;
- l = me.lastChild;
-
- if(l)
- l.nextSibling = other;
- else
- me.firstChild = other;
-
- other.prevSibling = l;
- other.nextSibling = NULL;
- me.lastChild = other;
-}
-
-void AnimHost_removeAnim(entity me, entity other)
-{
- if(other.parent != me)
- error("Can't remove from wrong AnimHost!");
-
- other.parent = NULL;
-
- entity n, p;
- n = other.nextSibling;
- p = other.prevSibling;
-
- if(p)
- p.nextSibling = n;
- else
- me.firstChild = n;
-
- if(n)
- n.prevSibling = p;
- else
- me.lastChild = p;
- remove(other);
-}
-
-void AnimHost_removeAllAnim(entity me)
-{
- entity e, tmp;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- tmp = e;
- e = tmp.prevSibling;
- me.removeAnim(me, tmp);
- }
-}
-
-void AnimHost_removeObjAnim(entity me, entity obj)
-{
- entity e, tmp;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- if (e.object == obj)
- {
- tmp = e;
- e = tmp.prevSibling;
- me.removeAnim(me, tmp);
- }
- }
-}
-
-void AnimHost_stopAllAnim(entity me)
-{
- entity e;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- e.stopAnim(e);
- }
-}
-
-void AnimHost_stopObjAnim(entity me, entity obj)
-{
- entity e;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- if (e.object == obj)
- {
- e.stopAnim(e);
- }
- }
-}
-
-void AnimHost_resumeAllAnim(entity me)
-{
- entity e;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- e.resumeAnim(e);
- }
-}
-
-void AnimHost_resumeObjAnim(entity me, entity obj)
-{
- entity e;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- if (e.object == obj)
- {
- e.resumeAnim(e);
- }
- }
-}
-
-void AnimHost_finishAllAnim(entity me)
-{
- entity e, tmp;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- tmp = e;
- e = tmp.prevSibling;
- tmp.finishAnim(tmp);
- }
-}
-
-void AnimHost_finishObjAnim(entity me, entity obj)
-{
- entity e, tmp;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- if (e.object == obj)
- {
- tmp = e;
- e = tmp.prevSibling;
- tmp.finishAnim(tmp);
- }
- }
-}
-
-void AnimHost_tickAll(entity me)
-{
- entity e, tmp;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- e.tick(e, time);
- if (e.isFinished(e))
- {
- tmp = e;
- e = tmp.prevSibling;
- me.removeAnim(me, tmp);
- }
- }
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(AnimHost) EXTENDS(Object)
+ METHOD(AnimHost, addAnim, void(entity, entity))
+ METHOD(AnimHost, removeAnim, void(entity, entity))
+ METHOD(AnimHost, removeAllAnim, void(entity))
+ METHOD(AnimHost, removeObjAnim, void(entity, entity))
+ METHOD(AnimHost, stopAllAnim, void(entity))
+ METHOD(AnimHost, stopObjAnim, void(entity, entity))
+ METHOD(AnimHost, resumeAllAnim, void(entity))
+ METHOD(AnimHost, resumeObjAnim, void(entity, entity))
+ METHOD(AnimHost, finishAllAnim, void(entity))
+ METHOD(AnimHost, finishObjAnim, void(entity, entity))
+ METHOD(AnimHost, tickAll, void(entity))
+ ATTRIB(AnimHost, firstChild, entity, NULL)
+ ATTRIB(AnimHost, lastChild, entity, NULL)
+ENDCLASS(AnimHost)
+.entity nextSibling;
+.entity prevSibling;
+#endif
+
+#ifdef IMPLEMENTATION
+void AnimHost_addAnim(entity me, entity other)
+{
+ if(other.parent)
+ error("Can't add already added anim!");
+
+ if(other.isFinished(other))
+ error("Can't add finished anim!");
+
+ other.parent = me;
+
+ entity l;
+ l = me.lastChild;
+
+ if(l)
+ l.nextSibling = other;
+ else
+ me.firstChild = other;
+
+ other.prevSibling = l;
+ other.nextSibling = NULL;
+ me.lastChild = other;
+}
+
+void AnimHost_removeAnim(entity me, entity other)
+{
+ if(other.parent != me)
+ error("Can't remove from wrong AnimHost!");
+
+ other.parent = NULL;
+
+ entity n, p;
+ n = other.nextSibling;
+ p = other.prevSibling;
+
+ if(p)
+ p.nextSibling = n;
+ else
+ me.firstChild = n;
+
+ if(n)
+ n.prevSibling = p;
+ else
+ me.lastChild = p;
+ remove(other);
+}
+
+void AnimHost_removeAllAnim(entity me)
+{
+ entity e, tmp;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ tmp = e;
+ e = tmp.prevSibling;
+ me.removeAnim(me, tmp);
+ }
+}
+
+void AnimHost_removeObjAnim(entity me, entity obj)
+{
+ entity e, tmp;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if (e.object == obj)
+ {
+ tmp = e;
+ e = tmp.prevSibling;
+ me.removeAnim(me, tmp);
+ }
+ }
+}
+
+void AnimHost_stopAllAnim(entity me)
+{
+ entity e;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ e.stopAnim(e);
+ }
+}
+
+void AnimHost_stopObjAnim(entity me, entity obj)
+{
+ entity e;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if (e.object == obj)
+ {
+ e.stopAnim(e);
+ }
+ }
+}
+
+void AnimHost_resumeAllAnim(entity me)
+{
+ entity e;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ e.resumeAnim(e);
+ }
+}
+
+void AnimHost_resumeObjAnim(entity me, entity obj)
+{
+ entity e;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if (e.object == obj)
+ {
+ e.resumeAnim(e);
+ }
+ }
+}
+
+void AnimHost_finishAllAnim(entity me)
+{
+ entity e, tmp;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ tmp = e;
+ e = tmp.prevSibling;
+ tmp.finishAnim(tmp);
+ }
+}
+
+void AnimHost_finishObjAnim(entity me, entity obj)
+{
+ entity e, tmp;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if (e.object == obj)
+ {
+ tmp = e;
+ e = tmp.prevSibling;
+ tmp.finishAnim(tmp);
+ }
+ }
+}
+
+void AnimHost_tickAll(entity me)
+{
+ entity e, tmp;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ e.tick(e, time);
+ if (e.isFinished(e))
+ {
+ tmp = e;
+ e = tmp.prevSibling;
+ me.removeAnim(me, tmp);
+ }
+ }
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(Easing) EXTENDS(Animation)
- METHOD(Easing, calcValue, float(entity, float, float, float, float))
- METHOD(Easing, setMath, void(entity, float(float, float, float, float)))
- ATTRIB(Easing, math, float(float, float, float, float), easingLinear)
-ENDCLASS(Easing)
-entity makeHostedEasing(entity, void(entity, float), float(float, float, float, float), float, float, float);
-entity makeEasing(entity, void(entity, float), float(float, float, float, float), float, float, float, float);
-float easingLinear(float, float, float, float);
-float easingQuadIn(float, float, float, float);
-float easingQuadOut(float, float, float, float);
-float easingQuadInOut(float, float, float, float);
-#endif
-
-#ifdef IMPLEMENTATION
-entity makeHostedEasing(entity obj, void(entity, float) objSetter, float(float, float, float, float) func, float animDuration, float animStartValue, float animEnd)
-{
- entity me;
- me = makeEasing(obj, objSetter, func, time, animDuration, animStartValue, animEnd);
- anim.addAnim(anim, me);
- return me;
-}
-
-entity makeEasing(entity obj, void(entity, float) objSetter, float(float, float, float, float) func, float animStartTime, float animDuration, float animStartValue, float animEnd)
-{
- entity me;
- me = spawnEasing();
- me.configureAnimation(me, obj, objSetter, animStartTime, animDuration, animStartValue, animEnd);
- me.setMath(me, func);
- return me;
-}
-
-float Easing_calcValue(entity me, float tickTime, float animDuration, float animStart, float animDelta)
-{
- return me.math(tickTime, animDuration, animStart, animDelta);
-}
-
-void Easing_setMath(entity me, float(float, float, float, float) func)
-{
- me.math = func;
-}
-
-float easingLinear(float tickTime, float animDuration, float animStart, float animDelta)
-{
- return (animDelta * (tickTime / animDuration)) + animStart;
-}
-
-float easingQuadIn(float tickTime, float animDuration, float animStart, float animDelta)
-{
- float frac = tickTime / animDuration;
- return (animDelta * frac * frac) + animStart;
-}
-
-float easingQuadOut(float tickTime, float animDuration, float animStart, float animDelta)
-{
- float frac = tickTime / animDuration;
- return (-animDelta * frac * (frac - 2)) + animStart;
-}
-
-float easingQuadInOut(float tickTime, float animDuration, float animStart, float animDelta)
-{
- if (tickTime < (animDuration / 2))
- {
- return easingQuadIn(tickTime, (animDuration / 2), animStart, (animDelta / 2));
- }
- else
- {
- return easingQuadOut((tickTime - (animDuration / 2)), (animDuration / 2), (animStart + (animDelta / 2)), (animDelta / 2));
- }
-}
-
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(Easing) EXTENDS(Animation)
+ METHOD(Easing, calcValue, float(entity, float, float, float, float))
+ METHOD(Easing, setMath, void(entity, float(float, float, float, float)))
+ ATTRIB(Easing, math, float(float, float, float, float), easingLinear)
+ENDCLASS(Easing)
+entity makeHostedEasing(entity, void(entity, float), float(float, float, float, float), float, float, float);
+entity makeEasing(entity, void(entity, float), float(float, float, float, float), float, float, float, float);
+float easingLinear(float, float, float, float);
+float easingQuadIn(float, float, float, float);
+float easingQuadOut(float, float, float, float);
+float easingQuadInOut(float, float, float, float);
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeHostedEasing(entity obj, void(entity, float) objSetter, float(float, float, float, float) func, float animDuration, float animStartValue, float animEnd)
+{
+ entity me;
+ me = makeEasing(obj, objSetter, func, time, animDuration, animStartValue, animEnd);
+ anim.addAnim(anim, me);
+ return me;
+}
+
+entity makeEasing(entity obj, void(entity, float) objSetter, float(float, float, float, float) func, float animStartTime, float animDuration, float animStartValue, float animEnd)
+{
+ entity me;
+ me = spawnEasing();
+ me.configureAnimation(me, obj, objSetter, animStartTime, animDuration, animStartValue, animEnd);
+ me.setMath(me, func);
+ return me;
+}
+
+float Easing_calcValue(entity me, float tickTime, float animDuration, float animStart, float animDelta)
+{
+ return me.math(tickTime, animDuration, animStart, animDelta);
+}
+
+void Easing_setMath(entity me, float(float, float, float, float) func)
+{
+ me.math = func;
+}
+
+float easingLinear(float tickTime, float animDuration, float animStart, float animDelta)
+{
+ return (animDelta * (tickTime / animDuration)) + animStart;
+}
+
+float easingQuadIn(float tickTime, float animDuration, float animStart, float animDelta)
+{
+ float frac = tickTime / animDuration;
+ return (animDelta * frac * frac) + animStart;
+}
+
+float easingQuadOut(float tickTime, float animDuration, float animStart, float animDelta)
+{
+ float frac = tickTime / animDuration;
+ return (-animDelta * frac * (frac - 2)) + animStart;
+}
+
+float easingQuadInOut(float tickTime, float animDuration, float animStart, float animDelta)
+{
+ if (tickTime < (animDuration / 2))
+ {
+ return easingQuadIn(tickTime, (animDuration / 2), animStart, (animDelta / 2));
+ }
+ else
+ {
+ return easingQuadOut((tickTime - (animDuration / 2)), (animDuration / 2), (animStart + (animDelta / 2)), (animDelta / 2));
+ }
+}
+
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(Keyframe) EXTENDS(Animation)
- METHOD(Keyframe, addEasing, entity(entity, float, float, float(float, float, float, float)))
- METHOD(Keyframe, addAnim, void(entity, entity))
- METHOD(Keyframe, calcValue, float(entity, float, float, float, float))
- ATTRIB(Keyframe, currentChild, entity, NULL)
- ATTRIB(Keyframe, firstChild, entity, NULL)
- ATTRIB(Keyframe, lastChild, entity, NULL)
-ENDCLASS(Keyframe)
-entity makeHostedKeyframe(entity, void(entity, float), float, float, float);
-entity makeKeyframe(entity, void(entity, float), float, float, float);
-float getNewChildStart(entity);
-float getNewChildDuration(entity, float);
-float getNewChildValue(entity);
-#endif
-
-#ifdef IMPLEMENTATION
-entity makeHostedKeyframe(entity obj, void(entity, float) objSetter, float animDuration, float animStart, float animEnd)
-{
- entity me;
- me = makeKeyframe(obj, objSetter, animDuration, animStart, animEnd);
- anim.addAnim(anim, me);
- return me;
-}
-
-entity makeKeyframe(entity obj, void(entity, float) objSetter, float animDuration, float animStart, float animEnd)
-{
- entity me;
- me = spawnKeyframe();
- me.configureAnimation(me, obj, objSetter, time, animDuration, animStart, animEnd);
- return me;
-}
-
-entity Keyframe_addEasing(entity me, float animDurationTime, float animEnd, float(float, float, float, float) func)
-{
- entity other;
- other = makeEasing(me.object, me.setter, func, getNewChildStart(me), getNewChildDuration(me, animDurationTime), getNewChildValue(me), animEnd);
- me.addAnim(me, other);
- return other;
-}
-
-float getNewChildStart(entity me)
-{
- if (me.lastChild)
- return (me.lastChild.startTime + me.lastChild.duration);
- else
- return 0;
-}
-
-float getNewChildDuration(entity me, float durationTime)
-{
- float dura, maxDura;
- maxDura = me.duration;
- if (me.lastChild) maxDura = maxDura - (me.lastChild.startTime + me.lastChild.duration);
- dura = durationTime;
- if (0 >= dura || dura > maxDura) dura = maxDura;
- return dura;
-}
-
-float getNewChildValue(entity me)
-{
- if (me.lastChild)
- return (me.lastChild.startValue + me.lastChild.delta);
- else
- return me.startValue;
-}
-
-void Keyframe_addAnim(entity me, entity other)
-{
- if(other.parent)
- error("Can't add already added anim!");
-
- if(other.isFinished(other))
- error("Can't add finished anim!");
-
- other.parent = me;
-
- entity l;
- l = me.lastChild;
-
- if(l)
- l.nextSibling = other;
- else
- {
- me.currentChild = other;
- me.firstChild = other;
- }
-
- other.prevSibling = l;
- other.nextSibling = NULL;
- me.lastChild = other;
-}
-
-float Keyframe_calcValue(entity me, float tickTime, float animDuration, float animStartValue, float animDelta)
-{
- if (me.currentChild)
- if (me.currentChild.isFinished(me.currentChild))
- me.currentChild = me.currentChild.nextSibling;
-
- if (me.currentChild)
- {
- me.currentChild.tick(me.currentChild, tickTime);
- return me.currentChild.value;
- }
-
- return animStartValue + animDelta;
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(Keyframe) EXTENDS(Animation)
+ METHOD(Keyframe, addEasing, entity(entity, float, float, float(float, float, float, float)))
+ METHOD(Keyframe, addAnim, void(entity, entity))
+ METHOD(Keyframe, calcValue, float(entity, float, float, float, float))
+ ATTRIB(Keyframe, currentChild, entity, NULL)
+ ATTRIB(Keyframe, firstChild, entity, NULL)
+ ATTRIB(Keyframe, lastChild, entity, NULL)
+ENDCLASS(Keyframe)
+entity makeHostedKeyframe(entity, void(entity, float), float, float, float);
+entity makeKeyframe(entity, void(entity, float), float, float, float);
+float getNewChildStart(entity);
+float getNewChildDuration(entity, float);
+float getNewChildValue(entity);
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeHostedKeyframe(entity obj, void(entity, float) objSetter, float animDuration, float animStart, float animEnd)
+{
+ entity me;
+ me = makeKeyframe(obj, objSetter, animDuration, animStart, animEnd);
+ anim.addAnim(anim, me);
+ return me;
+}
+
+entity makeKeyframe(entity obj, void(entity, float) objSetter, float animDuration, float animStart, float animEnd)
+{
+ entity me;
+ me = spawnKeyframe();
+ me.configureAnimation(me, obj, objSetter, time, animDuration, animStart, animEnd);
+ return me;
+}
+
+entity Keyframe_addEasing(entity me, float animDurationTime, float animEnd, float(float, float, float, float) func)
+{
+ entity other;
+ other = makeEasing(me.object, me.setter, func, getNewChildStart(me), getNewChildDuration(me, animDurationTime), getNewChildValue(me), animEnd);
+ me.addAnim(me, other);
+ return other;
+}
+
+float getNewChildStart(entity me)
+{
+ if (me.lastChild)
+ return (me.lastChild.startTime + me.lastChild.duration);
+ else
+ return 0;
+}
+
+float getNewChildDuration(entity me, float durationTime)
+{
+ float dura, maxDura;
+ maxDura = me.duration;
+ if (me.lastChild) maxDura = maxDura - (me.lastChild.startTime + me.lastChild.duration);
+ dura = durationTime;
+ if (0 >= dura || dura > maxDura) dura = maxDura;
+ return dura;
+}
+
+float getNewChildValue(entity me)
+{
+ if (me.lastChild)
+ return (me.lastChild.startValue + me.lastChild.delta);
+ else
+ return me.startValue;
+}
+
+void Keyframe_addAnim(entity me, entity other)
+{
+ if(other.parent)
+ error("Can't add already added anim!");
+
+ if(other.isFinished(other))
+ error("Can't add finished anim!");
+
+ other.parent = me;
+
+ entity l;
+ l = me.lastChild;
+
+ if(l)
+ l.nextSibling = other;
+ else
+ {
+ me.currentChild = other;
+ me.firstChild = other;
+ }
+
+ other.prevSibling = l;
+ other.nextSibling = NULL;
+ me.lastChild = other;
+}
+
+float Keyframe_calcValue(entity me, float tickTime, float animDuration, float animStartValue, float animDelta)
+{
+ if (me.currentChild)
+ if (me.currentChild.isFinished(me.currentChild))
+ me.currentChild = me.currentChild.nextSibling;
+
+ if (me.currentChild)
+ {
+ me.currentChild.tick(me.currentChild, tickTime);
+ return me.currentChild.value;
+ }
+
+ return animStartValue + animDelta;
+}
+#endif
+++ /dev/null
-#include "anim/animhost.c"
-#include "anim/animation.c"
-#include "anim/easing.c"
-#include "anim/keyframe.c"
-#include "item.c"
-#include "item/container.c"
-#include "item/inputcontainer.c"
-#include "item/nexposee.c"
-#include "item/modalcontroller.c"
-#include "item/image.c"
-#include "item/label.c"
-#include "item/button.c"
-#include "item/checkbox.c"
-#include "item/radiobutton.c"
-#include "item/borderimage.c"
-#include "item/slider.c"
-#include "item/dialog.c"
-#include "item/tab.c"
-#include "item/textslider.c"
-#include "item/listbox.c"
-#include "item/inputbox.c"
-#include "xonotic/dialog.c"
-#include "xonotic/tab.c"
-#include "xonotic/mainwindow.c"
-#include "xonotic/button.c"
-#include "xonotic/bigbutton.c"
-#include "xonotic/commandbutton.c"
-#include "xonotic/bigcommandbutton.c"
-#include "xonotic/textlabel.c"
-#include "xonotic/dialog_firstrun.c"
-#include "xonotic/dialog_teamselect.c"
-#include "xonotic/dialog_sandboxtools.c"
-#include "xonotic/dialog_monstertools.c"
-#include "xonotic/dialog_settings.c"
-#include "xonotic/dialog_settings_video.c"
-#include "xonotic/dialog_settings_effects.c"
-#include "xonotic/dialog_settings_audio.c"
-#include "xonotic/dialog_settings_game.c"
-#include "xonotic/dialog_settings_user.c"
-#include "xonotic/dialog_settings_user_languagewarning.c"
-#include "xonotic/dialog_settings_misc.c"
-#include "xonotic/dialog_multiplayer.c"
-#include "xonotic/dialog_multiplayer_profile.c"
-#include "xonotic/tabcontroller.c"
-#include "xonotic/slider.c"
-#include "xonotic/slider_resolution.c"
-#include "xonotic/checkbox.c"
-#include "xonotic/checkbox_string.c"
-#include "xonotic/weaponarenacheckbox.c"
-#include "xonotic/radiobutton.c"
-#include "xonotic/nexposee.c"
-#include "xonotic/rootdialog.c"
-#include "xonotic/textslider.c"
-#include "xonotic/colorbutton.c"
-#include "xonotic/dialog_multiplayer_join.c"
-#include "xonotic/dialog_multiplayer_join_serverinfo.c"
-#include "xonotic/playerlist.c"
-#include "xonotic/listbox.c"
-#include "xonotic/serverlist.c"
-#include "xonotic/inputbox.c"
-#include "xonotic/dialog_quit.c"
-#include "xonotic/dialog_multiplayer_create.c"
-#include "xonotic/dialog_multiplayer_create_mutators.c"
-#include "xonotic/dialog_multiplayer_create_mapinfo.c"
-#include "xonotic/gametypelist.c"
-#include "xonotic/maplist.c"
-#include "xonotic/skinlist.c"
-#include "xonotic/languagelist.c"
-#include "xonotic/image.c"
-#include "xonotic/crosshairbutton.c"
-#include "xonotic/playermodel.c"
-#include "xonotic/checkbox_slider_invalid.c"
-#include "xonotic/charmap.c"
-#include "xonotic/keybinder.c"
-#include "xonotic/dialog_settings_input.c"
-#include "xonotic/dialog_settings_input_userbind.c"
-#include "xonotic/slider_decibels.c"
-#include "xonotic/dialog_singleplayer.c"
-#include "xonotic/campaign.c"
-#include "xonotic/dialog_singleplayer_winner.c"
-#include "xonotic/dialog_credits.c"
-#include "xonotic/credits.c"
-#include "xonotic/dialog_settings_game_crosshair.c"
-#include "xonotic/dialog_settings_game_hud.c"
-#include "xonotic/dialog_settings_game_hudconfirm.c"
-#include "xonotic/dialog_settings_game_model.c"
-#include "xonotic/dialog_settings_game_messages.c"
-#include "xonotic/dialog_settings_game_view.c"
-#include "xonotic/dialog_settings_game_weapons.c"
-#include "xonotic/weaponslist.c"
-#include "xonotic/dialog_multiplayer_media.c"
-#include "xonotic/dialog_multiplayer_media_demo.c"
-#include "xonotic/dialog_multiplayer_media_demo_startconfirm.c"
-#include "xonotic/dialog_multiplayer_media_demo_timeconfirm.c"
-#include "xonotic/demolist.c"
-#include "xonotic/screenshotimage.c"
-#include "xonotic/dialog_multiplayer_media_screenshot.c"
-#include "xonotic/dialog_multiplayer_media_screenshot_viewer.c"
-#include "xonotic/screenshotlist.c"
-#include "xonotic/statslist.c"
-#include "xonotic/dialog_multiplayer_media_musicplayer.c"
-#include "xonotic/soundlist.c"
-#include "xonotic/playlist.c"
-#include "xonotic/colorpicker.c"
-#include "xonotic/colorpicker_string.c"
-#include "xonotic/cvarlist.c"
-#include "xonotic/dialog_settings_misc_cvars.c"
-#include "xonotic/dialog_hudsetup_exit.c"
-#include "xonotic/dialog_hudpanel_notification.c"
-#include "xonotic/dialog_hudpanel_ammo.c"
-#include "xonotic/dialog_hudpanel_healtharmor.c"
-#include "xonotic/dialog_hudpanel_powerups.c"
-#include "xonotic/dialog_hudpanel_racetimer.c"
-#include "xonotic/dialog_hudpanel_pressedkeys.c"
-#include "xonotic/dialog_hudpanel_radar.c"
-#include "xonotic/dialog_hudpanel_score.c"
-#include "xonotic/dialog_hudpanel_timer.c"
-#include "xonotic/dialog_hudpanel_vote.c"
-#include "xonotic/dialog_hudpanel_modicons.c"
-#include "xonotic/dialog_hudpanel_chat.c"
-#include "xonotic/dialog_hudpanel_engineinfo.c"
-#include "xonotic/dialog_hudpanel_infomessages.c"
-#include "xonotic/dialog_hudpanel_weapons.c"
-#include "xonotic/dialog_hudpanel_physics.c"
-#include "xonotic/dialog_hudpanel_centerprint.c"
-#include "xonotic/dialog_hudpanel_buffs.c"
-#include "xonotic/slider_picmip.c"
-#include "xonotic/slider_particles.c"
-#include "xonotic/slider_sbfadetime.c"
-#include "xonotic/dialog_settings_misc_reset.c"
--- /dev/null
+#include "anim/animhost.qc"
+#include "anim/animation.qc"
+#include "anim/easing.qc"
+#include "anim/keyframe.qc"
+#include "item.qc"
+#include "item/container.qc"
+#include "item/inputcontainer.qc"
+#include "item/nexposee.qc"
+#include "item/modalcontroller.qc"
+#include "item/image.qc"
+#include "item/label.qc"
+#include "item/button.qc"
+#include "item/checkbox.qc"
+#include "item/radiobutton.qc"
+#include "item/borderimage.qc"
+#include "item/slider.qc"
+#include "item/dialog.qc"
+#include "item/tab.qc"
+#include "item/textslider.qc"
+#include "item/listbox.qc"
+#include "item/inputbox.qc"
+#include "xonotic/dialog.qc"
+#include "xonotic/tab.qc"
+#include "xonotic/mainwindow.qc"
+#include "xonotic/button.qc"
+#include "xonotic/bigbutton.qc"
+#include "xonotic/commandbutton.qc"
+#include "xonotic/bigcommandbutton.qc"
+#include "xonotic/textlabel.qc"
+#include "xonotic/dialog_firstrun.qc"
+#include "xonotic/dialog_teamselect.qc"
+#include "xonotic/dialog_sandboxtools.qc"
+#include "xonotic/dialog_monstertools.qc"
+#include "xonotic/dialog_settings.qc"
+#include "xonotic/dialog_settings_video.qc"
+#include "xonotic/dialog_settings_effects.qc"
+#include "xonotic/dialog_settings_audio.qc"
+#include "xonotic/dialog_settings_game.qc"
+#include "xonotic/dialog_settings_user.qc"
+#include "xonotic/dialog_settings_user_languagewarning.qc"
+#include "xonotic/dialog_settings_misc.qc"
+#include "xonotic/dialog_multiplayer.qc"
+#include "xonotic/dialog_multiplayer_profile.qc"
+#include "xonotic/tabcontroller.qc"
+#include "xonotic/slider.qc"
+#include "xonotic/slider_resolution.qc"
+#include "xonotic/checkbox.qc"
+#include "xonotic/checkbox_string.qc"
+#include "xonotic/weaponarenacheckbox.qc"
+#include "xonotic/radiobutton.qc"
+#include "xonotic/nexposee.qc"
+#include "xonotic/rootdialog.qc"
+#include "xonotic/textslider.qc"
+#include "xonotic/colorbutton.qc"
+#include "xonotic/dialog_multiplayer_join.qc"
+#include "xonotic/dialog_multiplayer_join_serverinfo.qc"
+#include "xonotic/playerlist.qc"
+#include "xonotic/listbox.qc"
+#include "xonotic/serverlist.qc"
+#include "xonotic/inputbox.qc"
+#include "xonotic/dialog_quit.qc"
+#include "xonotic/dialog_multiplayer_create.qc"
+#include "xonotic/dialog_multiplayer_create_mutators.qc"
+#include "xonotic/dialog_multiplayer_create_mapinfo.qc"
+#include "xonotic/gametypelist.qc"
+#include "xonotic/maplist.qc"
+#include "xonotic/skinlist.qc"
+#include "xonotic/languagelist.qc"
+#include "xonotic/image.qc"
+#include "xonotic/crosshairbutton.qc"
+#include "xonotic/playermodel.qc"
+#include "xonotic/checkbox_slider_invalid.qc"
+#include "xonotic/charmap.qc"
+#include "xonotic/keybinder.qc"
+#include "xonotic/dialog_settings_input.qc"
+#include "xonotic/dialog_settings_input_userbind.qc"
+#include "xonotic/slider_decibels.qc"
+#include "xonotic/dialog_singleplayer.qc"
+#include "xonotic/campaign.qc"
+#include "xonotic/dialog_singleplayer_winner.qc"
+#include "xonotic/dialog_credits.qc"
+#include "xonotic/credits.qc"
+#include "xonotic/dialog_settings_game_crosshair.qc"
+#include "xonotic/dialog_settings_game_hud.qc"
+#include "xonotic/dialog_settings_game_hudconfirm.qc"
+#include "xonotic/dialog_settings_game_model.qc"
+#include "xonotic/dialog_settings_game_messages.qc"
+#include "xonotic/dialog_settings_game_view.qc"
+#include "xonotic/dialog_settings_game_weapons.qc"
+#include "xonotic/weaponslist.qc"
+#include "xonotic/dialog_multiplayer_media.qc"
+#include "xonotic/dialog_multiplayer_media_demo.qc"
+#include "xonotic/dialog_multiplayer_media_demo_startconfirm.qc"
+#include "xonotic/dialog_multiplayer_media_demo_timeconfirm.qc"
+#include "xonotic/demolist.qc"
+#include "xonotic/screenshotimage.qc"
+#include "xonotic/dialog_multiplayer_media_screenshot.qc"
+#include "xonotic/dialog_multiplayer_media_screenshot_viewer.qc"
+#include "xonotic/screenshotlist.qc"
+#include "xonotic/statslist.qc"
+#include "xonotic/dialog_multiplayer_media_musicplayer.qc"
+#include "xonotic/soundlist.qc"
+#include "xonotic/playlist.qc"
+#include "xonotic/colorpicker.qc"
+#include "xonotic/colorpicker_string.qc"
+#include "xonotic/cvarlist.qc"
+#include "xonotic/dialog_settings_misc_cvars.qc"
+#include "xonotic/dialog_hudsetup_exit.qc"
+#include "xonotic/dialog_hudpanel_notification.qc"
+#include "xonotic/dialog_hudpanel_ammo.qc"
+#include "xonotic/dialog_hudpanel_healtharmor.qc"
+#include "xonotic/dialog_hudpanel_powerups.qc"
+#include "xonotic/dialog_hudpanel_racetimer.qc"
+#include "xonotic/dialog_hudpanel_pressedkeys.qc"
+#include "xonotic/dialog_hudpanel_radar.qc"
+#include "xonotic/dialog_hudpanel_score.qc"
+#include "xonotic/dialog_hudpanel_timer.qc"
+#include "xonotic/dialog_hudpanel_vote.qc"
+#include "xonotic/dialog_hudpanel_modicons.qc"
+#include "xonotic/dialog_hudpanel_chat.qc"
+#include "xonotic/dialog_hudpanel_engineinfo.qc"
+#include "xonotic/dialog_hudpanel_infomessages.qc"
+#include "xonotic/dialog_hudpanel_weapons.qc"
+#include "xonotic/dialog_hudpanel_physics.qc"
+#include "xonotic/dialog_hudpanel_centerprint.qc"
+#include "xonotic/dialog_hudpanel_buffs.qc"
+#include "xonotic/slider_picmip.qc"
+#include "xonotic/slider_particles.qc"
+#include "xonotic/slider_sbfadetime.qc"
+#include "xonotic/dialog_settings_misc_reset.qc"
+++ /dev/null
-#ifdef INTERFACE
-CLASS(Item) EXTENDS(Object)
- METHOD(Item, draw, void(entity))
- METHOD(Item, keyDown, float(entity, float, float, float))
- METHOD(Item, keyUp, float(entity, float, float, float))
- METHOD(Item, mouseMove, float(entity, vector))
- METHOD(Item, mousePress, float(entity, vector))
- METHOD(Item, mouseDrag, float(entity, vector))
- METHOD(Item, mouseRelease, float(entity, vector))
- METHOD(Item, focusEnter, void(entity))
- METHOD(Item, focusLeave, void(entity))
- METHOD(Item, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Item, relinquishFocus, void(entity))
- METHOD(Item, showNotify, void(entity))
- METHOD(Item, hideNotify, void(entity))
- METHOD(Item, toString, string(entity))
- METHOD(Item, destroy, void(entity))
- ATTRIB(Item, focused, float, 0)
- ATTRIB(Item, focusable, float, 0)
- ATTRIB(Item, parent, entity, NULL)
- ATTRIB(Item, preferredFocusPriority, float, 0)
- ATTRIB(Item, origin, vector, '0 0 0')
- ATTRIB(Item, size, vector, '0 0 0')
- ATTRIB(Item, tooltip, string, string_null)
-ENDCLASS(Item)
-#endif
-
-#ifdef IMPLEMENTATION
-void Item_destroy(entity me)
-{
- // free memory associated with me
-}
-
-void Item_relinquishFocus(entity me)
-{
- if(me.parent)
- if(me.parent.instanceOfContainer)
- me.parent.setFocus(me.parent, NULL);
-}
-
-void Item_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- me.origin = absOrigin;
- me.size = absSize;
-}
-
-float autocvar_menu_showboxes;
-void Item_draw(entity me)
-{
- if(autocvar_menu_showboxes)
- {
- vector rgb = '1 0 1';
- float a = fabs(autocvar_menu_showboxes);
-
- // don't draw containers and border images
- if(me.instanceOfContainer || me.instanceOfBorderImage)
- {
- rgb = '0 0 0';
- a = 0;
- }
-
-#if 0
- // hack to detect multi drawing
- float r = random() * 3;
- if(r >= 2)
- rgb = '1 0 0';
- else if(r >= 1)
- rgb = '0 1 0';
- else
- rgb = '0 0 1';
-#endif
- if(autocvar_menu_showboxes < 0)
- {
- draw_Fill('0 0 0', '0.5 0.5 0', rgb, a);
- draw_Fill('0.5 0.5 0', '0.5 0.5 0', rgb, a);
- }
- if(autocvar_menu_showboxes > 0)
- {
- draw_Fill('0 0 0', '1 1 0', rgb, a);
- }
- }
-}
-
-void Item_showNotify(entity me)
-{
-}
-
-void Item_hideNotify(entity me)
-{
-}
-
-float Item_keyDown(entity me, float scan, float ascii, float shift)
-{
- return 0; // unhandled
-}
-
-float Item_keyUp(entity me, float scan, float ascii, float shift)
-{
- return 0; // unhandled
-}
-
-float Item_mouseMove(entity me, vector pos)
-{
- return 0; // unhandled
-}
-
-float Item_mousePress(entity me, vector pos)
-{
- return 0; // unhandled
-}
-
-float Item_mouseDrag(entity me, vector pos)
-{
- return 0; // unhandled
-}
-
-float Item_mouseRelease(entity me, vector pos)
-{
- return 0; // unhandled
-}
-
-void Item_focusEnter(entity me)
-{
-}
-
-void Item_focusLeave(entity me)
-{
-}
-
-string Item_toString(entity me)
-{
- return string_null;
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(Item) EXTENDS(Object)
+ METHOD(Item, draw, void(entity))
+ METHOD(Item, keyDown, float(entity, float, float, float))
+ METHOD(Item, keyUp, float(entity, float, float, float))
+ METHOD(Item, mouseMove, float(entity, vector))
+ METHOD(Item, mousePress, float(entity, vector))
+ METHOD(Item, mouseDrag, float(entity, vector))
+ METHOD(Item, mouseRelease, float(entity, vector))
+ METHOD(Item, focusEnter, void(entity))
+ METHOD(Item, focusLeave, void(entity))
+ METHOD(Item, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(Item, relinquishFocus, void(entity))
+ METHOD(Item, showNotify, void(entity))
+ METHOD(Item, hideNotify, void(entity))
+ METHOD(Item, toString, string(entity))
+ METHOD(Item, destroy, void(entity))
+ ATTRIB(Item, focused, float, 0)
+ ATTRIB(Item, focusable, float, 0)
+ ATTRIB(Item, parent, entity, NULL)
+ ATTRIB(Item, preferredFocusPriority, float, 0)
+ ATTRIB(Item, origin, vector, '0 0 0')
+ ATTRIB(Item, size, vector, '0 0 0')
+ ATTRIB(Item, tooltip, string, string_null)
+ENDCLASS(Item)
+#endif
+
+#ifdef IMPLEMENTATION
+void Item_destroy(entity me)
+{
+ // free memory associated with me
+}
+
+void Item_relinquishFocus(entity me)
+{
+ if(me.parent)
+ if(me.parent.instanceOfContainer)
+ me.parent.setFocus(me.parent, NULL);
+}
+
+void Item_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ me.origin = absOrigin;
+ me.size = absSize;
+}
+
+float autocvar_menu_showboxes;
+void Item_draw(entity me)
+{
+ if(autocvar_menu_showboxes)
+ {
+ vector rgb = '1 0 1';
+ float a = fabs(autocvar_menu_showboxes);
+
+ // don't draw containers and border images
+ if(me.instanceOfContainer || me.instanceOfBorderImage)
+ {
+ rgb = '0 0 0';
+ a = 0;
+ }
+
+#if 0
+ // hack to detect multi drawing
+ float r = random() * 3;
+ if(r >= 2)
+ rgb = '1 0 0';
+ else if(r >= 1)
+ rgb = '0 1 0';
+ else
+ rgb = '0 0 1';
+#endif
+ if(autocvar_menu_showboxes < 0)
+ {
+ draw_Fill('0 0 0', '0.5 0.5 0', rgb, a);
+ draw_Fill('0.5 0.5 0', '0.5 0.5 0', rgb, a);
+ }
+ if(autocvar_menu_showboxes > 0)
+ {
+ draw_Fill('0 0 0', '1 1 0', rgb, a);
+ }
+ }
+}
+
+void Item_showNotify(entity me)
+{
+}
+
+void Item_hideNotify(entity me)
+{
+}
+
+float Item_keyDown(entity me, float scan, float ascii, float shift)
+{
+ return 0; // unhandled
+}
+
+float Item_keyUp(entity me, float scan, float ascii, float shift)
+{
+ return 0; // unhandled
+}
+
+float Item_mouseMove(entity me, vector pos)
+{
+ return 0; // unhandled
+}
+
+float Item_mousePress(entity me, vector pos)
+{
+ return 0; // unhandled
+}
+
+float Item_mouseDrag(entity me, vector pos)
+{
+ return 0; // unhandled
+}
+
+float Item_mouseRelease(entity me, vector pos)
+{
+ return 0; // unhandled
+}
+
+void Item_focusEnter(entity me)
+{
+}
+
+void Item_focusLeave(entity me)
+{
+}
+
+string Item_toString(entity me)
+{
+ return string_null;
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(BorderImage) EXTENDS(Label)
- METHOD(BorderImage, configureBorderImage, void(entity, string, float, vector, string, float))
- METHOD(BorderImage, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(BorderImage, recalcPositionWithText, void(entity, string))
- ATTRIB(BorderImage, isBold, float, 1)
- METHOD(BorderImage, draw, void(entity))
- ATTRIB(BorderImage, src, string, string_null)
- ATTRIB(BorderImage, borderHeight, float, 0)
- ATTRIB(BorderImage, borderVec, vector, '0 0 0')
- ATTRIB(BorderImage, color, vector, '1 1 1')
- ATTRIB(BorderImage, closeButton, entity, NULL)
- ATTRIB(BorderImage, realFontSize_Nexposeed, vector, '0 0 0')
- ATTRIB(BorderImage, realOrigin_Nexposeed, vector, '0 0 0')
- ATTRIB(BorderImage, isNexposeeTitleBar, float, 0)
- ATTRIB(BorderImage, zoomedOutTitleBarPosition, float, 0)
- ATTRIB(BorderImage, zoomedOutTitleBar, float, 0)
- ATTRIB(BorderImage, overrideRealOrigin, vector, '0 1 0')
- ATTRIB(BorderImage, saveRelOrigin, vector, '0 0 0')
- ATTRIB(BorderImage, saveRelSize, vector, '0 0 0')
-ENDCLASS(BorderImage)
-#endif
-
-#ifdef IMPLEMENTATION
-void BorderImage_recalcPositionWithText(entity me, string t)
-{
- if(me.isNexposeeTitleBar)
- {
- vector scrs;
- scrs = eX * conwidth + eY * conheight;
- me.resizeNotify(me, me.saveRelOrigin, me.saveRelSize, boxToGlobal(me.parent.Nexposee_smallOrigin, '0 0 0', scrs), boxToGlobalSize(me.parent.Nexposee_smallSize, scrs));
- SUPER(BorderImage).recalcPositionWithText(me, t);
- me.realOrigin_y = me.realFontSize_y * me.zoomedOutTitleBarPosition;
- me.realOrigin_Nexposeed = me.realOrigin;
- me.realFontSize_Nexposeed = me.realFontSize;
- me.resizeNotify(me, me.saveRelOrigin, me.saveRelSize, boxToGlobal(me.parent.Nexposee_initialOrigin, '0 0 0', scrs), boxToGlobalSize(me.parent.Nexposee_initialSize, scrs));
- }
- SUPER(BorderImage).recalcPositionWithText(me, t);
-}
-void BorderImage_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- me.isNexposeeTitleBar = 0;
- if(me.zoomedOutTitleBar)
- if(me.parent.parent.instanceOfNexposee)
- if(me.parent.instanceOfDialog)
- if(me == me.parent.frame)
- me.isNexposeeTitleBar = 1;
- me.saveRelOrigin = relOrigin;
- me.saveRelSize = relSize;
- SUPER(BorderImage).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
- me.borderVec_x = me.borderHeight / absSize_x;
- me.borderVec_y = me.borderHeight / absSize_y;
- me.realOrigin_y = 0.5 * (me.borderVec_y - me.realFontSize_y);
- if(me.closeButton)
- {
- // move the close button to the right place
- me.closeButton.Container_origin = '1 0 0' * (1 - me.borderVec_x);
- me.closeButton.Container_size = me.borderVec;
- me.closeButton.color = me.color;
- me.closeButton.colorC = me.color;
- me.closeButton.colorF = me.color;
- }
-}
-void BorderImage_configureBorderImage(entity me, string theTitle, float sz, vector theColor, string path, float theBorderHeight)
-{
- me.configureLabel(me, theTitle, sz, 0.5);
- me.src = path;
- me.color = theColor;
- me.borderHeight = theBorderHeight;
-}
-void BorderImage_draw(entity me)
-{
- if(me.src)
- draw_BorderPicture('0 0 0', me.src, '1 1 0', me.color, 1, me.borderVec);
-
- if(me.fontSize > 0)
- {
- if(me.recalcPos)
- me.recalcPositionWithText(me, me.text);
-
- if(me.isNexposeeTitleBar)
- {
- vector ro, rf, df;
-
- // me.parent.Nexposee_animationFactor 0 (small) or 1 (full)
- // default values are for 1
- ro = me.realOrigin;
- rf = me.realFontSize;
- df = draw_fontscale;
- me.realOrigin = ro * me.parent.Nexposee_animationFactor + me.realOrigin_Nexposeed * (1 - me.parent.Nexposee_animationFactor);
- me.realFontSize = rf * me.parent.Nexposee_animationFactor + me.realFontSize_Nexposeed * (1 - me.parent.Nexposee_animationFactor);
- draw_fontscale = globalToBoxSize(boxToGlobalSize(df, me.realFontSize), rf);
-
- SUPER(BorderImage).draw(me);
-
- // me.Nexposee_animationState 0 (small) or 1 (full)
- // default values are for 1
- me.realOrigin = ro;
- me.realFontSize = rf;
- draw_fontscale = df;
- }
- else
- SUPER(BorderImage).draw(me);
- }
- else
- {
- SUPER(BorderImage).draw(me);
- }
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(BorderImage) EXTENDS(Label)
+ METHOD(BorderImage, configureBorderImage, void(entity, string, float, vector, string, float))
+ METHOD(BorderImage, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(BorderImage, recalcPositionWithText, void(entity, string))
+ ATTRIB(BorderImage, isBold, float, 1)
+ METHOD(BorderImage, draw, void(entity))
+ ATTRIB(BorderImage, src, string, string_null)
+ ATTRIB(BorderImage, borderHeight, float, 0)
+ ATTRIB(BorderImage, borderVec, vector, '0 0 0')
+ ATTRIB(BorderImage, color, vector, '1 1 1')
+ ATTRIB(BorderImage, closeButton, entity, NULL)
+ ATTRIB(BorderImage, realFontSize_Nexposeed, vector, '0 0 0')
+ ATTRIB(BorderImage, realOrigin_Nexposeed, vector, '0 0 0')
+ ATTRIB(BorderImage, isNexposeeTitleBar, float, 0)
+ ATTRIB(BorderImage, zoomedOutTitleBarPosition, float, 0)
+ ATTRIB(BorderImage, zoomedOutTitleBar, float, 0)
+ ATTRIB(BorderImage, overrideRealOrigin, vector, '0 1 0')
+ ATTRIB(BorderImage, saveRelOrigin, vector, '0 0 0')
+ ATTRIB(BorderImage, saveRelSize, vector, '0 0 0')
+ENDCLASS(BorderImage)
+#endif
+
+#ifdef IMPLEMENTATION
+void BorderImage_recalcPositionWithText(entity me, string t)
+{
+ if(me.isNexposeeTitleBar)
+ {
+ vector scrs;
+ scrs = eX * conwidth + eY * conheight;
+ me.resizeNotify(me, me.saveRelOrigin, me.saveRelSize, boxToGlobal(me.parent.Nexposee_smallOrigin, '0 0 0', scrs), boxToGlobalSize(me.parent.Nexposee_smallSize, scrs));
+ SUPER(BorderImage).recalcPositionWithText(me, t);
+ me.realOrigin_y = me.realFontSize_y * me.zoomedOutTitleBarPosition;
+ me.realOrigin_Nexposeed = me.realOrigin;
+ me.realFontSize_Nexposeed = me.realFontSize;
+ me.resizeNotify(me, me.saveRelOrigin, me.saveRelSize, boxToGlobal(me.parent.Nexposee_initialOrigin, '0 0 0', scrs), boxToGlobalSize(me.parent.Nexposee_initialSize, scrs));
+ }
+ SUPER(BorderImage).recalcPositionWithText(me, t);
+}
+void BorderImage_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ me.isNexposeeTitleBar = 0;
+ if(me.zoomedOutTitleBar)
+ if(me.parent.parent.instanceOfNexposee)
+ if(me.parent.instanceOfDialog)
+ if(me == me.parent.frame)
+ me.isNexposeeTitleBar = 1;
+ me.saveRelOrigin = relOrigin;
+ me.saveRelSize = relSize;
+ SUPER(BorderImage).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+ me.borderVec_x = me.borderHeight / absSize_x;
+ me.borderVec_y = me.borderHeight / absSize_y;
+ me.realOrigin_y = 0.5 * (me.borderVec_y - me.realFontSize_y);
+ if(me.closeButton)
+ {
+ // move the close button to the right place
+ me.closeButton.Container_origin = '1 0 0' * (1 - me.borderVec_x);
+ me.closeButton.Container_size = me.borderVec;
+ me.closeButton.color = me.color;
+ me.closeButton.colorC = me.color;
+ me.closeButton.colorF = me.color;
+ }
+}
+void BorderImage_configureBorderImage(entity me, string theTitle, float sz, vector theColor, string path, float theBorderHeight)
+{
+ me.configureLabel(me, theTitle, sz, 0.5);
+ me.src = path;
+ me.color = theColor;
+ me.borderHeight = theBorderHeight;
+}
+void BorderImage_draw(entity me)
+{
+ if(me.src)
+ draw_BorderPicture('0 0 0', me.src, '1 1 0', me.color, 1, me.borderVec);
+
+ if(me.fontSize > 0)
+ {
+ if(me.recalcPos)
+ me.recalcPositionWithText(me, me.text);
+
+ if(me.isNexposeeTitleBar)
+ {
+ vector ro, rf, df;
+
+ // me.parent.Nexposee_animationFactor 0 (small) or 1 (full)
+ // default values are for 1
+ ro = me.realOrigin;
+ rf = me.realFontSize;
+ df = draw_fontscale;
+ me.realOrigin = ro * me.parent.Nexposee_animationFactor + me.realOrigin_Nexposeed * (1 - me.parent.Nexposee_animationFactor);
+ me.realFontSize = rf * me.parent.Nexposee_animationFactor + me.realFontSize_Nexposeed * (1 - me.parent.Nexposee_animationFactor);
+ draw_fontscale = globalToBoxSize(boxToGlobalSize(df, me.realFontSize), rf);
+
+ SUPER(BorderImage).draw(me);
+
+ // me.Nexposee_animationState 0 (small) or 1 (full)
+ // default values are for 1
+ me.realOrigin = ro;
+ me.realFontSize = rf;
+ draw_fontscale = df;
+ }
+ else
+ SUPER(BorderImage).draw(me);
+ }
+ else
+ {
+ SUPER(BorderImage).draw(me);
+ }
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(Button) EXTENDS(Label)
- METHOD(Button, configureButton, void(entity, string, float, string))
- METHOD(Button, draw, void(entity))
- METHOD(Button, showNotify, void(entity))
- METHOD(Button, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Button, keyDown, float(entity, float, float, float))
- METHOD(Button, mousePress, float(entity, vector))
- METHOD(Button, mouseDrag, float(entity, vector))
- METHOD(Button, mouseRelease, float(entity, vector))
- METHOD(Button, focusEnter, void(entity))
- ATTRIB(Button, onClick, void(entity, entity), func_null)
- ATTRIB(Button, onClickEntity, entity, NULL)
- ATTRIB(Button, src, string, string_null)
- ATTRIB(Button, srcSuffix, string, string_null)
- ATTRIB(Button, src2, string, string_null) // is centered, same aspect, and stretched to label size
- ATTRIB(Button, src2scale, float, 1)
- ATTRIB(Button, srcMulti, float, 1) // 0: button square left, text right; 1: button stretched, text over it
- ATTRIB(Button, buttonLeftOfText, float, 0)
- ATTRIB(Button, focusable, float, 1)
- ATTRIB(Button, pressed, float, 0)
- ATTRIB(Button, clickTime, float, 0)
- ATTRIB(Button, disabled, float, 0)
- ATTRIB(Button, disabledAlpha, float, 0.3)
- ATTRIB(Button, forcePressed, float, 0)
- ATTRIB(Button, color, vector, '1 1 1')
- ATTRIB(Button, colorC, vector, '1 1 1')
- ATTRIB(Button, colorF, vector, '1 1 1')
- ATTRIB(Button, colorD, vector, '1 1 1')
- ATTRIB(Button, color2, vector, '1 1 1')
- ATTRIB(Button, alpha2, float, 1)
-
- ATTRIB(Button, origin, vector, '0 0 0')
- ATTRIB(Button, size, vector, '0 0 0')
-ENDCLASS(Button)
-#endif
-
-#ifdef IMPLEMENTATION
-void Button_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- if(me.srcMulti)
- me.keepspaceLeft = 0;
- else
- me.keepspaceLeft = min(0.8, absSize_y / absSize_x);
- SUPER(Button).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
-}
-void Button_configureButton(entity me, string txt, float sz, string gfx)
-{
- SUPER(Button).configureLabel(me, txt, sz, me.srcMulti ? 0.5 : 0);
- me.src = gfx;
-}
-float Button_keyDown(entity me, float key, float ascii, float shift)
-{
- if(key == K_ENTER || key == K_SPACE || key == K_KP_ENTER)
- {
- me.clickTime = 0.1; // delayed for effect
- return 1;
- }
- return 0;
-}
-float Button_mouseDrag(entity me, vector pos)
-{
- me.pressed = 1;
- if(pos_x < 0) me.pressed = 0;
- if(pos_y < 0) me.pressed = 0;
- if(pos_x >= 1) me.pressed = 0;
- if(pos_y >= 1) me.pressed = 0;
- return 1;
-}
-float Button_mousePress(entity me, vector pos)
-{
- me.mouseDrag(me, pos); // verify coordinates
- return 1;
-}
-float Button_mouseRelease(entity me, vector pos)
-{
- me.mouseDrag(me, pos); // verify coordinates
- if(me.pressed)
- {
- if (!me.disabled)
- {
- if(cvar("menu_sounds"))
- localsound("sound/misc/menu2.wav");
- if(me.onClick)
- me.onClick(me, me.onClickEntity);
- }
- me.pressed = 0;
- }
- return 1;
-}
-void Button_showNotify(entity me)
-{
- me.focusable = !me.disabled;
-}
-void Button_focusEnter(entity me)
-{
- if(cvar("menu_sounds") > 1)
- localsound("sound/misc/menu1.wav");
- SUPER(Button).focusEnter(me);
-}
-void Button_draw(entity me)
-{
- vector bOrigin, bSize;
- float save;
-
- me.focusable = !me.disabled;
-
- save = draw_alpha;
- if(me.disabled)
- draw_alpha *= me.disabledAlpha;
-
- if(me.src)
- {
- if(me.srcMulti)
- {
- bOrigin = '0 0 0';
- bSize = '1 1 0';
- if(me.disabled)
- draw_ButtonPicture(bOrigin, strcat(me.src, "_d", me.srcSuffix), bSize, me.colorD, 1);
- else if(me.forcePressed || me.pressed || me.clickTime > 0)
- draw_ButtonPicture(bOrigin, strcat(me.src, "_c", me.srcSuffix), bSize, me.colorC, 1);
- else if(me.focused)
- draw_ButtonPicture(bOrigin, strcat(me.src, "_f", me.srcSuffix), bSize, me.colorF, 1);
- else
- draw_ButtonPicture(bOrigin, strcat(me.src, "_n", me.srcSuffix), bSize, me.color, 1);
- }
- else
- {
- if(me.realFontSize_y == 0)
- {
- bOrigin = '0 0 0';
- bSize = '1 1 0';
- }
- else
- {
- bOrigin = eY * (0.5 * (1 - me.realFontSize_y)) + eX * (0.5 * (me.keepspaceLeft - me.realFontSize_x));
- bSize = me.realFontSize;
- }
- if(me.disabled)
- draw_Picture(bOrigin, strcat(me.src, "_d", me.srcSuffix), bSize, me.colorD, 1);
- else if(me.forcePressed || me.pressed || me.clickTime > 0)
- draw_Picture(bOrigin, strcat(me.src, "_c", me.srcSuffix), bSize, me.colorC, 1);
- else if(me.focused)
- draw_Picture(bOrigin, strcat(me.src, "_f", me.srcSuffix), bSize, me.colorF, 1);
- else
- draw_Picture(bOrigin, strcat(me.src, "_n", me.srcSuffix), bSize, me.color, 1);
- }
- }
- if(me.src2)
- {
- bOrigin = me.keepspaceLeft * eX;
- bSize = eY + eX * (1 - me.keepspaceLeft);
-
- bOrigin += bSize * (0.5 - 0.5 * me.src2scale);
- bSize = bSize * me.src2scale;
-
- draw_Picture(bOrigin, me.src2, bSize, me.color2, me.alpha2);
- }
-
- draw_alpha = save;
-
- if(me.clickTime > 0 && me.clickTime <= frametime)
- {
- // keyboard click timer expired? Fire the event then.
- if (!me.disabled)
- if(me.onClick)
- me.onClick(me, me.onClickEntity);
- }
- me.clickTime -= frametime;
-
- SUPER(Button).draw(me);
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(Button) EXTENDS(Label)
+ METHOD(Button, configureButton, void(entity, string, float, string))
+ METHOD(Button, draw, void(entity))
+ METHOD(Button, showNotify, void(entity))
+ METHOD(Button, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(Button, keyDown, float(entity, float, float, float))
+ METHOD(Button, mousePress, float(entity, vector))
+ METHOD(Button, mouseDrag, float(entity, vector))
+ METHOD(Button, mouseRelease, float(entity, vector))
+ METHOD(Button, focusEnter, void(entity))
+ ATTRIB(Button, onClick, void(entity, entity), func_null)
+ ATTRIB(Button, onClickEntity, entity, NULL)
+ ATTRIB(Button, src, string, string_null)
+ ATTRIB(Button, srcSuffix, string, string_null)
+ ATTRIB(Button, src2, string, string_null) // is centered, same aspect, and stretched to label size
+ ATTRIB(Button, src2scale, float, 1)
+ ATTRIB(Button, srcMulti, float, 1) // 0: button square left, text right; 1: button stretched, text over it
+ ATTRIB(Button, buttonLeftOfText, float, 0)
+ ATTRIB(Button, focusable, float, 1)
+ ATTRIB(Button, pressed, float, 0)
+ ATTRIB(Button, clickTime, float, 0)
+ ATTRIB(Button, disabled, float, 0)
+ ATTRIB(Button, disabledAlpha, float, 0.3)
+ ATTRIB(Button, forcePressed, float, 0)
+ ATTRIB(Button, color, vector, '1 1 1')
+ ATTRIB(Button, colorC, vector, '1 1 1')
+ ATTRIB(Button, colorF, vector, '1 1 1')
+ ATTRIB(Button, colorD, vector, '1 1 1')
+ ATTRIB(Button, color2, vector, '1 1 1')
+ ATTRIB(Button, alpha2, float, 1)
+
+ ATTRIB(Button, origin, vector, '0 0 0')
+ ATTRIB(Button, size, vector, '0 0 0')
+ENDCLASS(Button)
+#endif
+
+#ifdef IMPLEMENTATION
+void Button_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ if(me.srcMulti)
+ me.keepspaceLeft = 0;
+ else
+ me.keepspaceLeft = min(0.8, absSize_y / absSize_x);
+ SUPER(Button).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+}
+void Button_configureButton(entity me, string txt, float sz, string gfx)
+{
+ SUPER(Button).configureLabel(me, txt, sz, me.srcMulti ? 0.5 : 0);
+ me.src = gfx;
+}
+float Button_keyDown(entity me, float key, float ascii, float shift)
+{
+ if(key == K_ENTER || key == K_SPACE || key == K_KP_ENTER)
+ {
+ me.clickTime = 0.1; // delayed for effect
+ return 1;
+ }
+ return 0;
+}
+float Button_mouseDrag(entity me, vector pos)
+{
+ me.pressed = 1;
+ if(pos_x < 0) me.pressed = 0;
+ if(pos_y < 0) me.pressed = 0;
+ if(pos_x >= 1) me.pressed = 0;
+ if(pos_y >= 1) me.pressed = 0;
+ return 1;
+}
+float Button_mousePress(entity me, vector pos)
+{
+ me.mouseDrag(me, pos); // verify coordinates
+ return 1;
+}
+float Button_mouseRelease(entity me, vector pos)
+{
+ me.mouseDrag(me, pos); // verify coordinates
+ if(me.pressed)
+ {
+ if (!me.disabled)
+ {
+ if(cvar("menu_sounds"))
+ localsound("sound/misc/menu2.wav");
+ if(me.onClick)
+ me.onClick(me, me.onClickEntity);
+ }
+ me.pressed = 0;
+ }
+ return 1;
+}
+void Button_showNotify(entity me)
+{
+ me.focusable = !me.disabled;
+}
+void Button_focusEnter(entity me)
+{
+ if(cvar("menu_sounds") > 1)
+ localsound("sound/misc/menu1.wav");
+ SUPER(Button).focusEnter(me);
+}
+void Button_draw(entity me)
+{
+ vector bOrigin, bSize;
+ float save;
+
+ me.focusable = !me.disabled;
+
+ save = draw_alpha;
+ if(me.disabled)
+ draw_alpha *= me.disabledAlpha;
+
+ if(me.src)
+ {
+ if(me.srcMulti)
+ {
+ bOrigin = '0 0 0';
+ bSize = '1 1 0';
+ if(me.disabled)
+ draw_ButtonPicture(bOrigin, strcat(me.src, "_d", me.srcSuffix), bSize, me.colorD, 1);
+ else if(me.forcePressed || me.pressed || me.clickTime > 0)
+ draw_ButtonPicture(bOrigin, strcat(me.src, "_c", me.srcSuffix), bSize, me.colorC, 1);
+ else if(me.focused)
+ draw_ButtonPicture(bOrigin, strcat(me.src, "_f", me.srcSuffix), bSize, me.colorF, 1);
+ else
+ draw_ButtonPicture(bOrigin, strcat(me.src, "_n", me.srcSuffix), bSize, me.color, 1);
+ }
+ else
+ {
+ if(me.realFontSize_y == 0)
+ {
+ bOrigin = '0 0 0';
+ bSize = '1 1 0';
+ }
+ else
+ {
+ bOrigin = eY * (0.5 * (1 - me.realFontSize_y)) + eX * (0.5 * (me.keepspaceLeft - me.realFontSize_x));
+ bSize = me.realFontSize;
+ }
+ if(me.disabled)
+ draw_Picture(bOrigin, strcat(me.src, "_d", me.srcSuffix), bSize, me.colorD, 1);
+ else if(me.forcePressed || me.pressed || me.clickTime > 0)
+ draw_Picture(bOrigin, strcat(me.src, "_c", me.srcSuffix), bSize, me.colorC, 1);
+ else if(me.focused)
+ draw_Picture(bOrigin, strcat(me.src, "_f", me.srcSuffix), bSize, me.colorF, 1);
+ else
+ draw_Picture(bOrigin, strcat(me.src, "_n", me.srcSuffix), bSize, me.color, 1);
+ }
+ }
+ if(me.src2)
+ {
+ bOrigin = me.keepspaceLeft * eX;
+ bSize = eY + eX * (1 - me.keepspaceLeft);
+
+ bOrigin += bSize * (0.5 - 0.5 * me.src2scale);
+ bSize = bSize * me.src2scale;
+
+ draw_Picture(bOrigin, me.src2, bSize, me.color2, me.alpha2);
+ }
+
+ draw_alpha = save;
+
+ if(me.clickTime > 0 && me.clickTime <= frametime)
+ {
+ // keyboard click timer expired? Fire the event then.
+ if (!me.disabled)
+ if(me.onClick)
+ me.onClick(me, me.onClickEntity);
+ }
+ me.clickTime -= frametime;
+
+ SUPER(Button).draw(me);
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-void CheckBox_Click(entity me, entity other);
-CLASS(CheckBox) EXTENDS(Button)
- METHOD(CheckBox, configureCheckBox, void(entity, string, float, string))
- METHOD(CheckBox, draw, void(entity))
- METHOD(CheckBox, toString, string(entity))
- METHOD(CheckBox, setChecked, void(entity, float))
- ATTRIB(CheckBox, useDownAsChecked, float, 0)
- ATTRIB(CheckBox, checked, float, 0)
- ATTRIB(CheckBox, onClick, void(entity, entity), CheckBox_Click)
- ATTRIB(CheckBox, srcMulti, float, 0)
- ATTRIB(CheckBox, disabled, float, 0)
-ENDCLASS(CheckBox)
-#endif
-
-#ifdef IMPLEMENTATION
-void CheckBox_setChecked(entity me, float val)
-{
- me.checked = val;
-}
-void CheckBox_Click(entity me, entity other)
-{
- me.setChecked(me, !me.checked);
-}
-string CheckBox_toString(entity me)
-{
- return strcat(SUPER(CheckBox).toString(me), ", ", me.checked ? "checked" : "unchecked");
-}
-void CheckBox_configureCheckBox(entity me, string txt, float sz, string gfx)
-{
- me.configureButton(me, txt, sz, gfx);
- me.align = 0;
-}
-void CheckBox_draw(entity me)
-{
- float s;
- s = me.pressed;
- if(me.useDownAsChecked)
- {
- me.srcSuffix = string_null;
- me.forcePressed = me.checked;
- }
- else
- me.srcSuffix = (me.checked ? "1" : "0");
- me.pressed = s;
- SUPER(CheckBox).draw(me);
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+void CheckBox_Click(entity me, entity other);
+CLASS(CheckBox) EXTENDS(Button)
+ METHOD(CheckBox, configureCheckBox, void(entity, string, float, string))
+ METHOD(CheckBox, draw, void(entity))
+ METHOD(CheckBox, toString, string(entity))
+ METHOD(CheckBox, setChecked, void(entity, float))
+ ATTRIB(CheckBox, useDownAsChecked, float, 0)
+ ATTRIB(CheckBox, checked, float, 0)
+ ATTRIB(CheckBox, onClick, void(entity, entity), CheckBox_Click)
+ ATTRIB(CheckBox, srcMulti, float, 0)
+ ATTRIB(CheckBox, disabled, float, 0)
+ENDCLASS(CheckBox)
+#endif
+
+#ifdef IMPLEMENTATION
+void CheckBox_setChecked(entity me, float val)
+{
+ me.checked = val;
+}
+void CheckBox_Click(entity me, entity other)
+{
+ me.setChecked(me, !me.checked);
+}
+string CheckBox_toString(entity me)
+{
+ return strcat(SUPER(CheckBox).toString(me), ", ", me.checked ? "checked" : "unchecked");
+}
+void CheckBox_configureCheckBox(entity me, string txt, float sz, string gfx)
+{
+ me.configureButton(me, txt, sz, gfx);
+ me.align = 0;
+}
+void CheckBox_draw(entity me)
+{
+ float s;
+ s = me.pressed;
+ if(me.useDownAsChecked)
+ {
+ me.srcSuffix = string_null;
+ me.forcePressed = me.checked;
+ }
+ else
+ me.srcSuffix = (me.checked ? "1" : "0");
+ me.pressed = s;
+ SUPER(CheckBox).draw(me);
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(Container) EXTENDS(Item)
- METHOD(Container, draw, void(entity))
- METHOD(Container, keyUp, float(entity, float, float, float))
- METHOD(Container, keyDown, float(entity, float, float, float))
- METHOD(Container, mouseMove, float(entity, vector))
- METHOD(Container, mousePress, float(entity, vector))
- METHOD(Container, mouseDrag, float(entity, vector))
- METHOD(Container, mouseRelease, float(entity, vector))
- METHOD(Container, focusLeave, void(entity))
- METHOD(Container, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Container, resizeNotifyLie, void(entity, vector, vector, vector, vector, .vector, .vector, .vector))
- METHOD(Container, addItem, void(entity, entity, vector, vector, float))
- METHOD(Container, addItemCentered, void(entity, entity, vector, float))
- METHOD(Container, moveItemAfter, void(entity, entity, entity))
- METHOD(Container, removeItem, void(entity, entity))
- METHOD(Container, setFocus, void(entity, entity))
- METHOD(Container, saveFocus, void(entity))
- METHOD(Container, setAlphaOf, void(entity, entity, float))
- METHOD(Container, itemFromPoint, entity(entity, vector))
- METHOD(Container, showNotify, void(entity))
- METHOD(Container, hideNotify, void(entity))
- METHOD(Container, preferredFocusedGrandChild, entity(entity))
- ATTRIB(Container, focusable, float, 0)
- ATTRIB(Container, firstChild, entity, NULL)
- ATTRIB(Container, lastChild, entity, NULL)
- ATTRIB(Container, focusedChild, entity, NULL)
- ATTRIB(Container, savedFocus, entity, NULL)
- ATTRIB(Container, shown, float, 0)
-
- METHOD(Container, enterSubitem, void(entity, entity))
- METHOD(Container, enterLieSubitem, void(entity, vector, vector, vector, float))
- METHOD(Container, leaveSubitem, void(entity))
-ENDCLASS(Container)
-.entity nextSibling;
-.entity prevSibling;
-.float resized;
-.vector Container_origin;
-.vector Container_size;
-.vector Container_fontscale;
-.float Container_alpha;
-.vector Container_save_shift;
-.vector Container_save_scale;
-.vector Container_save_fontscale;
-.float Container_save_alpha;
-#endif
-
-#ifdef IMPLEMENTATION
-void Container_enterSubitem(entity me, entity sub)
-{
- me.enterLieSubitem(me, sub.Container_origin, sub.Container_size, sub.Container_fontscale, sub.Container_alpha);
-}
-
-void Container_enterLieSubitem(entity me, vector o, vector s, vector f, float a)
-{
- me.Container_save_shift = draw_shift;
- me.Container_save_scale = draw_scale;
- me.Container_save_alpha = draw_alpha;
- me.Container_save_fontscale = draw_fontscale;
-
- draw_shift = boxToGlobal(o, draw_shift, draw_scale);
- draw_scale = boxToGlobalSize(s, draw_scale);
- if(f != '0 0 0')
- draw_fontscale = boxToGlobalSize(f, draw_fontscale);
- draw_alpha *= a;
-}
-
-void Container_leaveSubitem(entity me)
-{
- draw_shift = me.Container_save_shift;
- draw_scale = me.Container_save_scale;
- draw_alpha = me.Container_save_alpha;
- draw_fontscale = me.Container_save_fontscale;
-}
-
-void Container_showNotify(entity me)
-{
- entity e;
- if(me.shown)
- return;
- me.shown = 1;
- for(e = me.firstChild; e; e = e.nextSibling)
- if(e.Container_alpha > 0)
- e.showNotify(e);
-}
-
-void Container_hideNotify(entity me)
-{
- entity e;
- if (!me.shown)
- return;
- me.shown = 0;
- for(e = me.firstChild; e; e = e.nextSibling)
- if(e.Container_alpha > 0)
- e.hideNotify(e);
-}
-
-void Container_setAlphaOf(entity me, entity other, float theAlpha)
-{
- if(theAlpha <= 0)
- {
- if(other.Container_alpha > 0)
- other.hideNotify(other);
- }
- else // value > 0
- {
- if(other.Container_alpha <= 0)
- other.showNotify(other);
- }
- other.Container_alpha = theAlpha;
-}
-
-void Container_resizeNotifyLie(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize, .vector originField, .vector sizeField, .vector fontScaleField)
-{
- entity e;
- vector o, s;
- float d;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- o = e.originField;
- s = e.sizeField;
- me.enterLieSubitem(me, o, s, e.fontScaleField, e.Container_alpha);
- e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
- me.leaveSubitem(me);
- }
- do
- {
- d = 0;
- for(e = me.firstChild; e; e = e.nextSibling)
- if(e.resized)
- {
- e.resized = 0;
- d = 1;
- o = e.originField;
- s = e.sizeField;
- me.enterLieSubitem(me, o, s, e.fontScaleField, e.Container_alpha);
- e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
- me.leaveSubitem(me);
- }
- }
- while(d);
- SUPER(Container).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
-}
-
-void Container_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- me.resizeNotifyLie(me, relOrigin, relSize, absOrigin, absSize, Container_origin, Container_size, Container_fontscale);
-}
-
-entity Container_itemFromPoint(entity me, vector pos)
-{
- entity e;
- vector o, s;
- for(e = me.lastChild; e; e = e.prevSibling)
- {
- o = e.Container_origin;
- s = e.Container_size;
- if(pos_x < o_x) continue;
- if(pos_y < o_y) continue;
- if(pos_x >= o_x + s_x) continue;
- if(pos_y >= o_y + s_y) continue;
- return e;
- }
- return NULL;
-}
-
-void Container_draw(entity me)
-{
- entity e;
-
- me.focusable = 0;
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- if(e.focusable)
- me.focusable += 1;
- if(e.Container_alpha < 0.003) // can't change color values anyway
- continue;
- me.enterSubitem(me, e);
- e.draw(e);
- me.leaveSubitem(me);
- }
-
- SUPER(Container).draw(me);
-}
-
-void Container_focusLeave(entity me)
-{
- me.setFocus(me, NULL);
-}
-
-float Container_keyUp(entity me, float scan, float ascii, float shift)
-{
- entity f;
- float r;
- f = me.focusedChild;
- if(f)
- {
- me.enterSubitem(me, f);
- r = f.keyUp(f, scan, ascii, shift);
- me.leaveSubitem(me);
- return r;
- }
- return 0;
-}
-
-float Container_keyDown(entity me, float scan, float ascii, float shift)
-{
- entity f;
- float r;
- f = me.focusedChild;
- if(f)
- {
- me.enterSubitem(me, f);
- r = f.keyDown(f, scan, ascii, shift);
- me.leaveSubitem(me);
- return r;
- }
- return 0;
-}
-
-float Container_mouseMove(entity me, vector pos)
-{
- entity f;
- float r;
- f = me.focusedChild;
- if(f)
- {
- me.enterSubitem(me, f);
- r = f.mouseMove(f, globalToBox(pos, f.Container_origin, f.Container_size));
- me.leaveSubitem(me);
- return r;
- }
- return 0;
-}
-float Container_mousePress(entity me, vector pos)
-{
- entity f;
- float r;
- f = me.focusedChild;
- if(f)
- {
- me.enterSubitem(me, f);
- r = f.mousePress(f, globalToBox(pos, f.Container_origin, f.Container_size));
- me.leaveSubitem(me);
- return r;
- }
- return 0;
-}
-float Container_mouseDrag(entity me, vector pos)
-{
- entity f;
- float r;
- f = me.focusedChild;
- if(f)
- {
- me.enterSubitem(me, f);
- r = f.mouseDrag(f, globalToBox(pos, f.Container_origin, f.Container_size));
- me.leaveSubitem(me);
- return r;
- }
- return 0;
-}
-float Container_mouseRelease(entity me, vector pos)
-{
- entity f;
- float r;
- f = me.focusedChild;
- if(f)
- {
- me.enterSubitem(me, f);
- r = f.mouseRelease(f, globalToBox(pos, f.Container_origin, f.Container_size));
- me.leaveSubitem(me);
- return r;
- }
- return 0;
-}
-
-void Container_addItemCentered(entity me, entity other, vector theSize, float theAlpha)
-{
- me.addItem(me, other, '0.5 0.5 0' - 0.5 * theSize, theSize, theAlpha);
-}
-
-void Container_addItem(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)
-{
- if(other.parent)
- error("Can't add already added item!");
-
- if(other.focusable)
- me.focusable += 1;
-
- if(theSize_x > 1)
- {
- theOrigin_x -= 0.5 * (theSize_x - 1);
- theSize_x = 1;
- }
- if(theSize_y > 1)
- {
- theOrigin_y -= 0.5 * (theSize_y - 1);
- theSize_y = 1;
- }
- theOrigin_x = bound(0, theOrigin_x, 1 - theSize_x);
- theOrigin_y = bound(0, theOrigin_y, 1 - theSize_y);
-
- other.parent = me;
- other.Container_origin = theOrigin;
- other.Container_size = theSize;
- me.setAlphaOf(me, other, theAlpha);
-
- entity l;
- l = me.lastChild;
-
- if(l)
- l.nextSibling = other;
- else
- me.firstChild = other;
-
- other.prevSibling = l;
- other.nextSibling = NULL;
- me.lastChild = other;
-}
-
-void Container_removeItem(entity me, entity other)
-{
- if(other.parent != me)
- error("Can't remove from wrong container!");
-
- if(other.focusable)
- me.focusable -= 1;
-
- other.parent = NULL;
-
- entity n, p;
- n = other.nextSibling;
- p = other.prevSibling;
-
- if(p)
- p.nextSibling = n;
- else
- me.firstChild = n;
-
- if(n)
- n.prevSibling = p;
- else
- me.lastChild = p;
-}
-
-void Container_setFocus(entity me, entity other)
-{
- if(me.focusedChild == other)
- return;
-
- if(me.focusedChild)
- {
- me.focusedChild.focused = 0;
- me.focusedChild.focusLeave(me.focusedChild);
- me.focusedChild = NULL;
- }
-
- if(other)
- {
- if(!me.focused)
- error("Trying to set focus in a non-focused control!");
-
- if(me.savedFocus)
- {
- me.focusedChild = me.savedFocus;
- me.savedFocus = NULL;
- me.focusedChild.focused = 1;
- me.focusedChild.focusEnter(me.focusedChild);
-
- if(me.focusedChild.instanceOfContainer)
- me.focusedChild.setFocus(me.focusedChild, me.focusedChild.savedFocus);
- }
- else
- {
- me.focusedChild = other;
- me.focusedChild.focused = 1;
- me.focusedChild.focusEnter(me.focusedChild);
- }
- }
-}
-
-void Container_saveFocus(entity me)
-{
- me.savedFocus = me.focusedChild;
-
- if(me.focusedChild.instanceOfContainer)
- me.focusedChild.saveFocus(me.focusedChild);
-}
-
-void Container_moveItemAfter(entity me, entity other, entity dest)
-{
- // first: remove other from the chain
- entity n, p;
-
- if(other.parent != me)
- error("Can't move in wrong container!");
-
- n = other.nextSibling;
- p = other.prevSibling;
-
- if(p)
- p.nextSibling = n;
- else
- me.firstChild = n;
-
- if(n)
- n.prevSibling = p;
- else
- me.lastChild = p;
-
- // now other got removed. Insert it behind dest now.
- other.prevSibling = dest;
- if(dest)
- other.nextSibling = dest.nextSibling;
- else
- other.nextSibling = me.firstChild;
-
- if(dest)
- dest.nextSibling = other;
- else
- me.firstChild = other;
-
- if(other.nextSibling)
- other.nextSibling.prevSibling = other;
- else
- me.lastChild = other;
-}
-
-entity Container_preferredFocusedGrandChild(entity me)
-{
- entity e, e2;
- entity best;
-
- best = NULL;
-
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- if(e.instanceOfContainer)
- {
- e2 = e.preferredFocusedGrandChild(e);
- if(e2)
- if(!best || best.preferredFocusPriority < e2.preferredFocusPriority)
- best = e2;
- }
- if(e)
- if(!best || best.preferredFocusPriority < e.preferredFocusPriority)
- best = e;
- }
-
- return best;
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(Container) EXTENDS(Item)
+ METHOD(Container, draw, void(entity))
+ METHOD(Container, keyUp, float(entity, float, float, float))
+ METHOD(Container, keyDown, float(entity, float, float, float))
+ METHOD(Container, mouseMove, float(entity, vector))
+ METHOD(Container, mousePress, float(entity, vector))
+ METHOD(Container, mouseDrag, float(entity, vector))
+ METHOD(Container, mouseRelease, float(entity, vector))
+ METHOD(Container, focusLeave, void(entity))
+ METHOD(Container, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(Container, resizeNotifyLie, void(entity, vector, vector, vector, vector, .vector, .vector, .vector))
+ METHOD(Container, addItem, void(entity, entity, vector, vector, float))
+ METHOD(Container, addItemCentered, void(entity, entity, vector, float))
+ METHOD(Container, moveItemAfter, void(entity, entity, entity))
+ METHOD(Container, removeItem, void(entity, entity))
+ METHOD(Container, setFocus, void(entity, entity))
+ METHOD(Container, saveFocus, void(entity))
+ METHOD(Container, setAlphaOf, void(entity, entity, float))
+ METHOD(Container, itemFromPoint, entity(entity, vector))
+ METHOD(Container, showNotify, void(entity))
+ METHOD(Container, hideNotify, void(entity))
+ METHOD(Container, preferredFocusedGrandChild, entity(entity))
+ ATTRIB(Container, focusable, float, 0)
+ ATTRIB(Container, firstChild, entity, NULL)
+ ATTRIB(Container, lastChild, entity, NULL)
+ ATTRIB(Container, focusedChild, entity, NULL)
+ ATTRIB(Container, savedFocus, entity, NULL)
+ ATTRIB(Container, shown, float, 0)
+
+ METHOD(Container, enterSubitem, void(entity, entity))
+ METHOD(Container, enterLieSubitem, void(entity, vector, vector, vector, float))
+ METHOD(Container, leaveSubitem, void(entity))
+ENDCLASS(Container)
+.entity nextSibling;
+.entity prevSibling;
+.float resized;
+.vector Container_origin;
+.vector Container_size;
+.vector Container_fontscale;
+.float Container_alpha;
+.vector Container_save_shift;
+.vector Container_save_scale;
+.vector Container_save_fontscale;
+.float Container_save_alpha;
+#endif
+
+#ifdef IMPLEMENTATION
+void Container_enterSubitem(entity me, entity sub)
+{
+ me.enterLieSubitem(me, sub.Container_origin, sub.Container_size, sub.Container_fontscale, sub.Container_alpha);
+}
+
+void Container_enterLieSubitem(entity me, vector o, vector s, vector f, float a)
+{
+ me.Container_save_shift = draw_shift;
+ me.Container_save_scale = draw_scale;
+ me.Container_save_alpha = draw_alpha;
+ me.Container_save_fontscale = draw_fontscale;
+
+ draw_shift = boxToGlobal(o, draw_shift, draw_scale);
+ draw_scale = boxToGlobalSize(s, draw_scale);
+ if(f != '0 0 0')
+ draw_fontscale = boxToGlobalSize(f, draw_fontscale);
+ draw_alpha *= a;
+}
+
+void Container_leaveSubitem(entity me)
+{
+ draw_shift = me.Container_save_shift;
+ draw_scale = me.Container_save_scale;
+ draw_alpha = me.Container_save_alpha;
+ draw_fontscale = me.Container_save_fontscale;
+}
+
+void Container_showNotify(entity me)
+{
+ entity e;
+ if(me.shown)
+ return;
+ me.shown = 1;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ if(e.Container_alpha > 0)
+ e.showNotify(e);
+}
+
+void Container_hideNotify(entity me)
+{
+ entity e;
+ if (!me.shown)
+ return;
+ me.shown = 0;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ if(e.Container_alpha > 0)
+ e.hideNotify(e);
+}
+
+void Container_setAlphaOf(entity me, entity other, float theAlpha)
+{
+ if(theAlpha <= 0)
+ {
+ if(other.Container_alpha > 0)
+ other.hideNotify(other);
+ }
+ else // value > 0
+ {
+ if(other.Container_alpha <= 0)
+ other.showNotify(other);
+ }
+ other.Container_alpha = theAlpha;
+}
+
+void Container_resizeNotifyLie(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize, .vector originField, .vector sizeField, .vector fontScaleField)
+{
+ entity e;
+ vector o, s;
+ float d;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ o = e.originField;
+ s = e.sizeField;
+ me.enterLieSubitem(me, o, s, e.fontScaleField, e.Container_alpha);
+ e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
+ me.leaveSubitem(me);
+ }
+ do
+ {
+ d = 0;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ if(e.resized)
+ {
+ e.resized = 0;
+ d = 1;
+ o = e.originField;
+ s = e.sizeField;
+ me.enterLieSubitem(me, o, s, e.fontScaleField, e.Container_alpha);
+ e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
+ me.leaveSubitem(me);
+ }
+ }
+ while(d);
+ SUPER(Container).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+}
+
+void Container_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ me.resizeNotifyLie(me, relOrigin, relSize, absOrigin, absSize, Container_origin, Container_size, Container_fontscale);
+}
+
+entity Container_itemFromPoint(entity me, vector pos)
+{
+ entity e;
+ vector o, s;
+ for(e = me.lastChild; e; e = e.prevSibling)
+ {
+ o = e.Container_origin;
+ s = e.Container_size;
+ if(pos_x < o_x) continue;
+ if(pos_y < o_y) continue;
+ if(pos_x >= o_x + s_x) continue;
+ if(pos_y >= o_y + s_y) continue;
+ return e;
+ }
+ return NULL;
+}
+
+void Container_draw(entity me)
+{
+ entity e;
+
+ me.focusable = 0;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if(e.focusable)
+ me.focusable += 1;
+ if(e.Container_alpha < 0.003) // can't change color values anyway
+ continue;
+ me.enterSubitem(me, e);
+ e.draw(e);
+ me.leaveSubitem(me);
+ }
+
+ SUPER(Container).draw(me);
+}
+
+void Container_focusLeave(entity me)
+{
+ me.setFocus(me, NULL);
+}
+
+float Container_keyUp(entity me, float scan, float ascii, float shift)
+{
+ entity f;
+ float r;
+ f = me.focusedChild;
+ if(f)
+ {
+ me.enterSubitem(me, f);
+ r = f.keyUp(f, scan, ascii, shift);
+ me.leaveSubitem(me);
+ return r;
+ }
+ return 0;
+}
+
+float Container_keyDown(entity me, float scan, float ascii, float shift)
+{
+ entity f;
+ float r;
+ f = me.focusedChild;
+ if(f)
+ {
+ me.enterSubitem(me, f);
+ r = f.keyDown(f, scan, ascii, shift);
+ me.leaveSubitem(me);
+ return r;
+ }
+ return 0;
+}
+
+float Container_mouseMove(entity me, vector pos)
+{
+ entity f;
+ float r;
+ f = me.focusedChild;
+ if(f)
+ {
+ me.enterSubitem(me, f);
+ r = f.mouseMove(f, globalToBox(pos, f.Container_origin, f.Container_size));
+ me.leaveSubitem(me);
+ return r;
+ }
+ return 0;
+}
+float Container_mousePress(entity me, vector pos)
+{
+ entity f;
+ float r;
+ f = me.focusedChild;
+ if(f)
+ {
+ me.enterSubitem(me, f);
+ r = f.mousePress(f, globalToBox(pos, f.Container_origin, f.Container_size));
+ me.leaveSubitem(me);
+ return r;
+ }
+ return 0;
+}
+float Container_mouseDrag(entity me, vector pos)
+{
+ entity f;
+ float r;
+ f = me.focusedChild;
+ if(f)
+ {
+ me.enterSubitem(me, f);
+ r = f.mouseDrag(f, globalToBox(pos, f.Container_origin, f.Container_size));
+ me.leaveSubitem(me);
+ return r;
+ }
+ return 0;
+}
+float Container_mouseRelease(entity me, vector pos)
+{
+ entity f;
+ float r;
+ f = me.focusedChild;
+ if(f)
+ {
+ me.enterSubitem(me, f);
+ r = f.mouseRelease(f, globalToBox(pos, f.Container_origin, f.Container_size));
+ me.leaveSubitem(me);
+ return r;
+ }
+ return 0;
+}
+
+void Container_addItemCentered(entity me, entity other, vector theSize, float theAlpha)
+{
+ me.addItem(me, other, '0.5 0.5 0' - 0.5 * theSize, theSize, theAlpha);
+}
+
+void Container_addItem(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)
+{
+ if(other.parent)
+ error("Can't add already added item!");
+
+ if(other.focusable)
+ me.focusable += 1;
+
+ if(theSize_x > 1)
+ {
+ theOrigin_x -= 0.5 * (theSize_x - 1);
+ theSize_x = 1;
+ }
+ if(theSize_y > 1)
+ {
+ theOrigin_y -= 0.5 * (theSize_y - 1);
+ theSize_y = 1;
+ }
+ theOrigin_x = bound(0, theOrigin_x, 1 - theSize_x);
+ theOrigin_y = bound(0, theOrigin_y, 1 - theSize_y);
+
+ other.parent = me;
+ other.Container_origin = theOrigin;
+ other.Container_size = theSize;
+ me.setAlphaOf(me, other, theAlpha);
+
+ entity l;
+ l = me.lastChild;
+
+ if(l)
+ l.nextSibling = other;
+ else
+ me.firstChild = other;
+
+ other.prevSibling = l;
+ other.nextSibling = NULL;
+ me.lastChild = other;
+}
+
+void Container_removeItem(entity me, entity other)
+{
+ if(other.parent != me)
+ error("Can't remove from wrong container!");
+
+ if(other.focusable)
+ me.focusable -= 1;
+
+ other.parent = NULL;
+
+ entity n, p;
+ n = other.nextSibling;
+ p = other.prevSibling;
+
+ if(p)
+ p.nextSibling = n;
+ else
+ me.firstChild = n;
+
+ if(n)
+ n.prevSibling = p;
+ else
+ me.lastChild = p;
+}
+
+void Container_setFocus(entity me, entity other)
+{
+ if(me.focusedChild == other)
+ return;
+
+ if(me.focusedChild)
+ {
+ me.focusedChild.focused = 0;
+ me.focusedChild.focusLeave(me.focusedChild);
+ me.focusedChild = NULL;
+ }
+
+ if(other)
+ {
+ if(!me.focused)
+ error("Trying to set focus in a non-focused control!");
+
+ if(me.savedFocus)
+ {
+ me.focusedChild = me.savedFocus;
+ me.savedFocus = NULL;
+ me.focusedChild.focused = 1;
+ me.focusedChild.focusEnter(me.focusedChild);
+
+ if(me.focusedChild.instanceOfContainer)
+ me.focusedChild.setFocus(me.focusedChild, me.focusedChild.savedFocus);
+ }
+ else
+ {
+ me.focusedChild = other;
+ me.focusedChild.focused = 1;
+ me.focusedChild.focusEnter(me.focusedChild);
+ }
+ }
+}
+
+void Container_saveFocus(entity me)
+{
+ me.savedFocus = me.focusedChild;
+
+ if(me.focusedChild.instanceOfContainer)
+ me.focusedChild.saveFocus(me.focusedChild);
+}
+
+void Container_moveItemAfter(entity me, entity other, entity dest)
+{
+ // first: remove other from the chain
+ entity n, p;
+
+ if(other.parent != me)
+ error("Can't move in wrong container!");
+
+ n = other.nextSibling;
+ p = other.prevSibling;
+
+ if(p)
+ p.nextSibling = n;
+ else
+ me.firstChild = n;
+
+ if(n)
+ n.prevSibling = p;
+ else
+ me.lastChild = p;
+
+ // now other got removed. Insert it behind dest now.
+ other.prevSibling = dest;
+ if(dest)
+ other.nextSibling = dest.nextSibling;
+ else
+ other.nextSibling = me.firstChild;
+
+ if(dest)
+ dest.nextSibling = other;
+ else
+ me.firstChild = other;
+
+ if(other.nextSibling)
+ other.nextSibling.prevSibling = other;
+ else
+ me.lastChild = other;
+}
+
+entity Container_preferredFocusedGrandChild(entity me)
+{
+ entity e, e2;
+ entity best;
+
+ best = NULL;
+
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if(e.instanceOfContainer)
+ {
+ e2 = e.preferredFocusedGrandChild(e);
+ if(e2)
+ if(!best || best.preferredFocusPriority < e2.preferredFocusPriority)
+ best = e2;
+ }
+ if(e)
+ if(!best || best.preferredFocusPriority < e.preferredFocusPriority)
+ best = e;
+ }
+
+ return best;
+}
+#endif
+++ /dev/null
-// Note: this class is called Dialog, but it can also handle a tab under the following conditions:
-// - isTabRoot is 0
-// - backgroundImage is the tab's background
-// - closable is 0
-// - rootDialog is 0
-// - title is ""
-// - marginTop is
-// - intendedHeight ends up to be the tab's actual height, or at least close
-// - titleFontSize is 0
-// - marginTop cancels out as much of titleHeight as needed (that is, it should be actualMarginTop - titleHeight)
-// To ensure the latter, you best create all tabs FIRST and insert the tabbed
-// control to your dialog THEN - with the right height
-//
-// a subclass may help with using this as a tab
-
-#ifdef INTERFACE
-CLASS(Dialog) EXTENDS(InputContainer)
- METHOD(Dialog, configureDialog, void(entity)) // no runtime configuration, all parameters are given in the code!
- METHOD(Dialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
- METHOD(Dialog, keyDown, float(entity, float, float, float))
- METHOD(Dialog, close, void(entity))
- METHOD(Dialog, addItemSimple, void(entity, float, float, float, float, entity, vector))
-
- METHOD(Dialog, TD, void(entity, float, float, entity))
- METHOD(Dialog, TDNoMargin, void(entity, float, float, entity, vector))
- METHOD(Dialog, TDempty, void(entity, float))
- METHOD(Dialog, setFirstColumn, void(entity, float))
- METHOD(Dialog, TR, void(entity))
- METHOD(Dialog, gotoRC, void(entity, float, float))
-
- ATTRIB(Dialog, isTabRoot, float, 1)
- ATTRIB(Dialog, closeButton, entity, NULL)
- ATTRIB(Dialog, intendedHeight, float, 0)
- ATTRIB(Dialog, itemOrigin, vector, '0 0 0')
- ATTRIB(Dialog, itemSize, vector, '0 0 0')
- ATTRIB(Dialog, itemSpacing, vector, '0 0 0')
- ATTRIB(Dialog, currentRow, float, 0)
- ATTRIB(Dialog, currentColumn, float, 0)
- ATTRIB(Dialog, firstColumn, float, 0)
-
- // to be customized
- ATTRIB(Dialog, closable, float, 1)
- ATTRIB(Dialog, title, string, "Form1") // ;)
- ATTRIB(Dialog, color, vector, '1 0.5 1')
- ATTRIB(Dialog, intendedWidth, float, 0)
- ATTRIB(Dialog, rows, float, 3)
- ATTRIB(Dialog, columns, float, 2)
-
- ATTRIB(Dialog, marginTop, float, 0) // pixels
- ATTRIB(Dialog, marginBottom, float, 0) // pixels
- ATTRIB(Dialog, marginLeft, float, 0) // pixels
- ATTRIB(Dialog, marginRight, float, 0) // pixels
- ATTRIB(Dialog, columnSpacing, float, 0) // pixels
- ATTRIB(Dialog, rowSpacing, float, 0) // pixels
- ATTRIB(Dialog, rowHeight, float, 0) // pixels
- ATTRIB(Dialog, titleHeight, float, 0) // pixels
- ATTRIB(Dialog, titleFontSize, float, 0) // pixels; if 0, title causes no margin
- ATTRIB(Dialog, zoomedOutTitleBarPosition, float, 0)
- ATTRIB(Dialog, zoomedOutTitleBar, float, 0)
-
- ATTRIB(Dialog, requiresConnection, float, 0) // set to TRUE if the dialog requires a connection to be opened
-
- ATTRIB(Dialog, backgroundImage, string, string_null)
- ATTRIB(Dialog, borderLines, float, 1)
- ATTRIB(Dialog, closeButtonImage, string, string_null)
-
- ATTRIB(Dialog, frame, entity, NULL)
-ENDCLASS(Dialog)
-#endif
-
-#ifdef IMPLEMENTATION
-void Dialog_Close(entity button, entity me)
-{
- me.close(me);
-}
-
-void Dialog_fill(entity me)
-{
-}
-
-void Dialog_addItemSimple(entity me, float row, float col, float rowspan, float colspan, entity e, vector v)
-{
- vector o, s;
- o = me.itemOrigin + eX * ( col * me.itemSpacing_x) + eY * ( row * me.itemSpacing_y);
- s = me.itemSize + eX * ((colspan - 1) * me.itemSpacing_x) + eY * ((rowspan - 1) * me.itemSpacing_y);
- o_x -= 0.5 * (me.itemSpacing_x - me.itemSize_x) * v_x;
- s_x += (me.itemSpacing_x - me.itemSize_x) * v_x;
- o_y -= 0.5 * (me.itemSpacing_y - me.itemSize_y) * v_y;
- s_y += (me.itemSpacing_y - me.itemSize_y) * v_y;
- me.addItem(me, e, o, s, 1);
-}
-
-void Dialog_gotoRC(entity me, float row, float col)
-{
- me.currentRow = row;
- me.currentColumn = col;
-}
-
-void Dialog_TR(entity me)
-{
- me.currentRow += 1;
- me.currentColumn = me.firstColumn;
-}
-
-void Dialog_TD(entity me, float rowspan, float colspan, entity e)
-{
- me.addItemSimple(me, me.currentRow, me.currentColumn, rowspan, colspan, e, '0 0 0');
- me.currentColumn += colspan;
-}
-
-void Dialog_TDNoMargin(entity me, float rowspan, float colspan, entity e, vector v)
-{
- me.addItemSimple(me, me.currentRow, me.currentColumn, rowspan, colspan, e, v);
- me.currentColumn += colspan;
-}
-
-void Dialog_setFirstColumn(entity me, float col)
-{
- me.firstColumn = col;
-}
-
-void Dialog_TDempty(entity me, float colspan)
-{
- me.currentColumn += colspan;
-}
-
-void Dialog_configureDialog(entity me)
-{
- float absWidth, absHeight;
-
- me.frame = spawnBorderImage();
- me.frame.configureBorderImage(me.frame, me.title, me.titleFontSize, me.color, me.backgroundImage, me.borderLines * me.titleHeight);
- me.frame.zoomedOutTitleBarPosition = me.zoomedOutTitleBarPosition;
- me.frame.zoomedOutTitleBar = me.zoomedOutTitleBar;
- me.frame.alpha = me.alpha;
- me.addItem(me, me.frame, '0 0 0', '1 1 0', 1);
-
- if (!me.titleFontSize)
- me.titleHeight = 0; // no title bar
-
- absWidth = me.intendedWidth * conwidth;
- absHeight = me.borderLines * me.titleHeight + me.marginTop + me.rows * me.rowHeight + (me.rows - 1) * me.rowSpacing + me.marginBottom;
- me.itemOrigin = eX * (me.marginLeft / absWidth)
- + eY * ((me.borderLines * me.titleHeight + me.marginTop) / absHeight);
- me.itemSize = eX * ((1 - (me.marginLeft + me.marginRight + me.columnSpacing * (me.columns - 1)) / absWidth) / me.columns)
- + eY * (me.rowHeight / absHeight);
- me.itemSpacing = me.itemSize
- + eX * (me.columnSpacing / absWidth)
- + eY * (me.rowSpacing / absHeight);
- me.intendedHeight = absHeight / conheight;
- me.currentRow = -1;
- me.currentColumn = -1;
-
- me.fill(me);
-
- if(me.closable && me.borderLines > 0)
- {
- entity closebutton;
- closebutton = me.closeButton = me.frame.closeButton = spawnButton();
- closebutton.configureButton(closebutton, "", 0, me.closeButtonImage);
- closebutton.onClick = Dialog_Close; closebutton.onClickEntity = me;
- closebutton.srcMulti = 0;
- me.addItem(me, closebutton, '0 0 0', '1 1 0', 1); // put it as LAST
- }
-}
-
-void Dialog_close(entity me)
-{
- if(me.parent.instanceOfNexposee)
- {
- ExposeeCloseButton_Click(me, me.parent);
- }
- else if(me.parent.instanceOfModalController)
- {
- DialogCloseButton_Click(me, me);
- }
-}
-
-float Dialog_keyDown(entity me, float key, float ascii, float shift)
-{
- if(me.closable)
- {
- if(key == K_ESCAPE)
- {
- me.close(me);
- return 1;
- }
- }
- return SUPER(Dialog).keyDown(me, key, ascii, shift);
-}
-#endif
--- /dev/null
+// Note: this class is called Dialog, but it can also handle a tab under the following conditions:
+// - isTabRoot is 0
+// - backgroundImage is the tab's background
+// - closable is 0
+// - rootDialog is 0
+// - title is ""
+// - marginTop is
+// - intendedHeight ends up to be the tab's actual height, or at least close
+// - titleFontSize is 0
+// - marginTop cancels out as much of titleHeight as needed (that is, it should be actualMarginTop - titleHeight)
+// To ensure the latter, you best create all tabs FIRST and insert the tabbed
+// control to your dialog THEN - with the right height
+//
+// a subclass may help with using this as a tab
+
+#ifdef INTERFACE
+CLASS(Dialog) EXTENDS(InputContainer)
+ METHOD(Dialog, configureDialog, void(entity)) // no runtime configuration, all parameters are given in the code!
+ METHOD(Dialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
+ METHOD(Dialog, keyDown, float(entity, float, float, float))
+ METHOD(Dialog, close, void(entity))
+ METHOD(Dialog, addItemSimple, void(entity, float, float, float, float, entity, vector))
+
+ METHOD(Dialog, TD, void(entity, float, float, entity))
+ METHOD(Dialog, TDNoMargin, void(entity, float, float, entity, vector))
+ METHOD(Dialog, TDempty, void(entity, float))
+ METHOD(Dialog, setFirstColumn, void(entity, float))
+ METHOD(Dialog, TR, void(entity))
+ METHOD(Dialog, gotoRC, void(entity, float, float))
+
+ ATTRIB(Dialog, isTabRoot, float, 1)
+ ATTRIB(Dialog, closeButton, entity, NULL)
+ ATTRIB(Dialog, intendedHeight, float, 0)
+ ATTRIB(Dialog, itemOrigin, vector, '0 0 0')
+ ATTRIB(Dialog, itemSize, vector, '0 0 0')
+ ATTRIB(Dialog, itemSpacing, vector, '0 0 0')
+ ATTRIB(Dialog, currentRow, float, 0)
+ ATTRIB(Dialog, currentColumn, float, 0)
+ ATTRIB(Dialog, firstColumn, float, 0)
+
+ // to be customized
+ ATTRIB(Dialog, closable, float, 1)
+ ATTRIB(Dialog, title, string, "Form1") // ;)
+ ATTRIB(Dialog, color, vector, '1 0.5 1')
+ ATTRIB(Dialog, intendedWidth, float, 0)
+ ATTRIB(Dialog, rows, float, 3)
+ ATTRIB(Dialog, columns, float, 2)
+
+ ATTRIB(Dialog, marginTop, float, 0) // pixels
+ ATTRIB(Dialog, marginBottom, float, 0) // pixels
+ ATTRIB(Dialog, marginLeft, float, 0) // pixels
+ ATTRIB(Dialog, marginRight, float, 0) // pixels
+ ATTRIB(Dialog, columnSpacing, float, 0) // pixels
+ ATTRIB(Dialog, rowSpacing, float, 0) // pixels
+ ATTRIB(Dialog, rowHeight, float, 0) // pixels
+ ATTRIB(Dialog, titleHeight, float, 0) // pixels
+ ATTRIB(Dialog, titleFontSize, float, 0) // pixels; if 0, title causes no margin
+ ATTRIB(Dialog, zoomedOutTitleBarPosition, float, 0)
+ ATTRIB(Dialog, zoomedOutTitleBar, float, 0)
+
+ ATTRIB(Dialog, requiresConnection, float, 0) // set to TRUE if the dialog requires a connection to be opened
+
+ ATTRIB(Dialog, backgroundImage, string, string_null)
+ ATTRIB(Dialog, borderLines, float, 1)
+ ATTRIB(Dialog, closeButtonImage, string, string_null)
+
+ ATTRIB(Dialog, frame, entity, NULL)
+ENDCLASS(Dialog)
+#endif
+
+#ifdef IMPLEMENTATION
+void Dialog_Close(entity button, entity me)
+{
+ me.close(me);
+}
+
+void Dialog_fill(entity me)
+{
+}
+
+void Dialog_addItemSimple(entity me, float row, float col, float rowspan, float colspan, entity e, vector v)
+{
+ vector o, s;
+ o = me.itemOrigin + eX * ( col * me.itemSpacing_x) + eY * ( row * me.itemSpacing_y);
+ s = me.itemSize + eX * ((colspan - 1) * me.itemSpacing_x) + eY * ((rowspan - 1) * me.itemSpacing_y);
+ o_x -= 0.5 * (me.itemSpacing_x - me.itemSize_x) * v_x;
+ s_x += (me.itemSpacing_x - me.itemSize_x) * v_x;
+ o_y -= 0.5 * (me.itemSpacing_y - me.itemSize_y) * v_y;
+ s_y += (me.itemSpacing_y - me.itemSize_y) * v_y;
+ me.addItem(me, e, o, s, 1);
+}
+
+void Dialog_gotoRC(entity me, float row, float col)
+{
+ me.currentRow = row;
+ me.currentColumn = col;
+}
+
+void Dialog_TR(entity me)
+{
+ me.currentRow += 1;
+ me.currentColumn = me.firstColumn;
+}
+
+void Dialog_TD(entity me, float rowspan, float colspan, entity e)
+{
+ me.addItemSimple(me, me.currentRow, me.currentColumn, rowspan, colspan, e, '0 0 0');
+ me.currentColumn += colspan;
+}
+
+void Dialog_TDNoMargin(entity me, float rowspan, float colspan, entity e, vector v)
+{
+ me.addItemSimple(me, me.currentRow, me.currentColumn, rowspan, colspan, e, v);
+ me.currentColumn += colspan;
+}
+
+void Dialog_setFirstColumn(entity me, float col)
+{
+ me.firstColumn = col;
+}
+
+void Dialog_TDempty(entity me, float colspan)
+{
+ me.currentColumn += colspan;
+}
+
+void Dialog_configureDialog(entity me)
+{
+ float absWidth, absHeight;
+
+ me.frame = spawnBorderImage();
+ me.frame.configureBorderImage(me.frame, me.title, me.titleFontSize, me.color, me.backgroundImage, me.borderLines * me.titleHeight);
+ me.frame.zoomedOutTitleBarPosition = me.zoomedOutTitleBarPosition;
+ me.frame.zoomedOutTitleBar = me.zoomedOutTitleBar;
+ me.frame.alpha = me.alpha;
+ me.addItem(me, me.frame, '0 0 0', '1 1 0', 1);
+
+ if (!me.titleFontSize)
+ me.titleHeight = 0; // no title bar
+
+ absWidth = me.intendedWidth * conwidth;
+ absHeight = me.borderLines * me.titleHeight + me.marginTop + me.rows * me.rowHeight + (me.rows - 1) * me.rowSpacing + me.marginBottom;
+ me.itemOrigin = eX * (me.marginLeft / absWidth)
+ + eY * ((me.borderLines * me.titleHeight + me.marginTop) / absHeight);
+ me.itemSize = eX * ((1 - (me.marginLeft + me.marginRight + me.columnSpacing * (me.columns - 1)) / absWidth) / me.columns)
+ + eY * (me.rowHeight / absHeight);
+ me.itemSpacing = me.itemSize
+ + eX * (me.columnSpacing / absWidth)
+ + eY * (me.rowSpacing / absHeight);
+ me.intendedHeight = absHeight / conheight;
+ me.currentRow = -1;
+ me.currentColumn = -1;
+
+ me.fill(me);
+
+ if(me.closable && me.borderLines > 0)
+ {
+ entity closebutton;
+ closebutton = me.closeButton = me.frame.closeButton = spawnButton();
+ closebutton.configureButton(closebutton, "", 0, me.closeButtonImage);
+ closebutton.onClick = Dialog_Close; closebutton.onClickEntity = me;
+ closebutton.srcMulti = 0;
+ me.addItem(me, closebutton, '0 0 0', '1 1 0', 1); // put it as LAST
+ }
+}
+
+void Dialog_close(entity me)
+{
+ if(me.parent.instanceOfNexposee)
+ {
+ ExposeeCloseButton_Click(me, me.parent);
+ }
+ else if(me.parent.instanceOfModalController)
+ {
+ DialogCloseButton_Click(me, me);
+ }
+}
+
+float Dialog_keyDown(entity me, float key, float ascii, float shift)
+{
+ if(me.closable)
+ {
+ if(key == K_ESCAPE)
+ {
+ me.close(me);
+ return 1;
+ }
+ }
+ return SUPER(Dialog).keyDown(me, key, ascii, shift);
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(Image) EXTENDS(Item)
- METHOD(Image, configureImage, void(entity, string))
- METHOD(Image, draw, void(entity))
- METHOD(Image, toString, string(entity))
- METHOD(Image, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Image, updateAspect, void(entity))
- METHOD(Image, initZoom, void(entity))
- METHOD(Image, setZoom, void(entity, float, float))
- METHOD(Image, drag_setStartPos, float(entity, vector))
- METHOD(Image, drag, float(entity, vector))
- ATTRIB(Image, src, string, string_null)
- ATTRIB(Image, color, vector, '1 1 1')
- ATTRIB(Image, forcedAspect, float, 0) // special values: -1 keep image aspect ratio, -2 keep image size but bound to the containing box, -3 always keep image size
- ATTRIB(Image, zoomBox, float, 0) // used by forcedAspect -2 when the image is larger than the containing box
- ATTRIB(Image, zoomFactor, float, 1)
- ATTRIB(Image, zoomOffset, vector, '0.5 0.5 0')
- ATTRIB(Image, zoomSnapToTheBox, float, 1) // snap the zoomed in image to the box borders when zooming/dragging it
- ATTRIB(Image, zoomTime, float, 0)
- ATTRIB(Image, zoomLimitedByTheBox, float, 0) // forbids zoom if image would be larger than the containing box
- ATTRIB(Image, zoomMax, float, 0)
- ATTRIB(Image, start_zoomOffset, vector, '0 0 0')
- ATTRIB(Image, start_coords, vector, '0 0 0')
- ATTRIB(Image, imgOrigin, vector, '0 0 0')
- ATTRIB(Image, imgSize, vector, '0 0 0')
-ENDCLASS(Image)
-#endif
-
-#ifdef IMPLEMENTATION
-string Image_toString(entity me)
-{
- return me.src;
-}
-void Image_configureImage(entity me, string path)
-{
- me.src = path;
-}
-void Image_initZoom(entity me)
-{
- me.zoomOffset = '0.5 0.5 0';
- me.zoomFactor = 1;
- if (me.forcedAspect == -2)
- me.zoomBox = -1; // calculate zoomBox at the first updateAspect call
- if (me.zoomLimitedByTheBox)
- me.zoomMax = -1; // calculate zoomMax at the first updateAspect call
-}
-
-void Image_draw(entity me)
-{
- if(me.imgSize_x > 1 || me.imgSize_y > 1)
- draw_SetClip();
- draw_Picture(me.imgOrigin, me.src, me.imgSize, me.color, 1);
- if(me.imgSize_x > 1 || me.imgSize_y > 1)
- draw_ClearClip();
- SUPER(Image).draw(me);
-}
-void Image_updateAspect(entity me)
-{
- float asp = 0;
- if(me.size_x <= 0 || me.size_y <= 0)
- return;
- if(me.forcedAspect == 0)
- {
- me.imgOrigin = '0 0 0';
- me.imgSize = '1 1 0';
- }
- else
- {
- vector sz = '0 0 0';
- if(me.forcedAspect < 0)
- {
- if (me.src != "")
- sz = draw_PictureSize(me.src);
- if(sz_x <= 0 || sz_y <= 0)
- {
- // image is broken or doesn't exist, set the size for the placeholder image
- sz_x = me.size_x;
- sz_y = me.size_y;
- }
- asp = sz_x / sz_y;
- }
- else
- asp = me.forcedAspect;
-
- if(me.forcedAspect <= -2)
- {
- me.imgSize_x = sz_x / me.size_x;
- me.imgSize_y = sz_y / me.size_y;
- if(me.zoomBox < 0 && (me.imgSize_x > 1 || me.imgSize_y > 1))
- {
- // image larger than the containing box, zoom it out to fit into the box
- if(me.size_x > asp * me.size_y)
- me.zoomBox = (me.size_y * asp / me.size_x) / me.imgSize_x;
- else
- me.zoomBox = (me.size_x / (asp * me.size_y)) / me.imgSize_y;
- me.zoomFactor = me.zoomBox;
- }
- }
- else
- {
- if(me.size_x > asp * me.size_y)
- {
- // x too large, so center x-wise
- me.imgSize = eY + eX * (me.size_y * asp / me.size_x);
- }
- else
- {
- // y too large, so center y-wise
- me.imgSize = eX + eY * (me.size_x / (asp * me.size_y));
- }
- }
- }
-
- if (me.zoomMax < 0)
- {
- if(me.zoomBox > 0)
- me.zoomMax = me.zoomBox;
- else
- {
- if(me.size_x > asp * me.size_y)
- me.zoomMax = (me.size_y * asp / me.size_x) / me.imgSize_x;
- else
- me.zoomMax = (me.size_x / (asp * me.size_y)) / me.imgSize_y;
- }
- }
-
- if (me.zoomMax > 0 && me.zoomFactor > me.zoomMax)
- me.zoomFactor = me.zoomMax;
- if (me.zoomFactor)
- me.imgSize = me.imgSize * me.zoomFactor;
-
- if(me.imgSize_x > 1 || me.imgSize_y > 1)
- {
- if(me.zoomSnapToTheBox)
- {
- if(me.imgSize_x > 1)
- me.zoomOffset_x = bound(0.5/me.imgSize_x, me.zoomOffset_x, 1 - 0.5/me.imgSize_x);
- else
- me.zoomOffset_x = bound(1 - 0.5/me.imgSize_x, me.zoomOffset_x, 0.5/me.imgSize_x);
-
- if(me.imgSize_y > 1)
- me.zoomOffset_y = bound(0.5/me.imgSize_y, me.zoomOffset_y, 1 - 0.5/me.imgSize_y);
- else
- me.zoomOffset_y = bound(1 - 0.5/me.imgSize_y, me.zoomOffset_y, 0.5/me.imgSize_y);
- }
- else
- {
- me.zoomOffset_x = bound(0, me.zoomOffset_x, 1);
- me.zoomOffset_y = bound(0, me.zoomOffset_y, 1);
- }
- }
- else
- me.zoomOffset = '0.5 0.5 0';
-
- me.imgOrigin_x = 0.5 - me.zoomOffset_x * me.imgSize_x;
- me.imgOrigin_y = 0.5 - me.zoomOffset_y * me.imgSize_y;
-}
-float Image_drag_setStartPos(entity me, vector coords)
-{
- //if(me.imgSize_x > 1 || me.imgSize_y > 1) // check disabled: mousewheel zoom may start from a non-zoomed-in image
- {
- me.start_zoomOffset = me.zoomOffset;
- me.start_coords = coords;
- }
- return 1;
-}
-float Image_drag(entity me, vector coords)
-{
- if(me.imgSize_x > 1 || me.imgSize_y > 1)
- {
- me.zoomOffset_x = me.start_zoomOffset_x + (me.start_coords_x - coords_x) / me.imgSize_x;
- me.zoomOffset_y = me.start_zoomOffset_y + (me.start_coords_y - coords_y) / me.imgSize_y;
- me.updateAspect(me);
- }
- return 1;
-}
-void Image_setZoom(entity me, float z, float atMousePosition)
-{
- float prev_zoomFactor;
- prev_zoomFactor = me.zoomFactor;
- if (z < 0) // multiply by the current zoomFactor (but can also snap to real dimensions or to box)
- {
- me.zoomFactor *= -z;
- float realSize_in_the_middle, boxSize_in_the_middle;
- realSize_in_the_middle = ((prev_zoomFactor - 1) * (me.zoomFactor - 1) < 0);
- boxSize_in_the_middle = (me.zoomBox > 0 && (prev_zoomFactor - me.zoomBox) * (me.zoomFactor - me.zoomBox) < 0);
- if (realSize_in_the_middle && boxSize_in_the_middle)
- {
- // snap to real dimensions or to box
- if (prev_zoomFactor < me.zoomFactor)
- me.zoomFactor = min(1, me.zoomBox);
- else
- me.zoomFactor = max(1, me.zoomBox);
- }
- else if (realSize_in_the_middle)
- me.zoomFactor = 1; // snap to real dimensions
- else if (boxSize_in_the_middle)
- me.zoomFactor = me.zoomBox; // snap to box
- }
- else if (z == 0) // reset (no zoom)
- {
- if (me.zoomBox > 0)
- me.zoomFactor = me.zoomBox;
- else
- me.zoomFactor = 1;
- }
- else // directly set
- me.zoomFactor = z;
- me.zoomFactor = bound(1/16, me.zoomFactor, 16);
- if (me.zoomMax > 0 && me.zoomFactor > me.zoomMax)
- me.zoomFactor = me.zoomMax;
- if (prev_zoomFactor != me.zoomFactor)
- {
- me.zoomTime = time;
- if (atMousePosition)
- {
- me.zoomOffset_x = me.start_zoomOffset_x + (me.start_coords_x - 0.5) / me.imgSize_x;
- me.zoomOffset_y = me.start_zoomOffset_y + (me.start_coords_y - 0.5) / me.imgSize_y;
- // updateAspect will reset zoomOffset to '0.5 0.5 0' if
- // with this zoomFactor the image will not be zoomed in
- // (updateAspect will check the new values of imgSize).
- }
- }
- me.updateAspect(me);
-}
-void Image_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- SUPER(Image).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
- me.updateAspect(me);
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(Image) EXTENDS(Item)
+ METHOD(Image, configureImage, void(entity, string))
+ METHOD(Image, draw, void(entity))
+ METHOD(Image, toString, string(entity))
+ METHOD(Image, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(Image, updateAspect, void(entity))
+ METHOD(Image, initZoom, void(entity))
+ METHOD(Image, setZoom, void(entity, float, float))
+ METHOD(Image, drag_setStartPos, float(entity, vector))
+ METHOD(Image, drag, float(entity, vector))
+ ATTRIB(Image, src, string, string_null)
+ ATTRIB(Image, color, vector, '1 1 1')
+ ATTRIB(Image, forcedAspect, float, 0) // special values: -1 keep image aspect ratio, -2 keep image size but bound to the containing box, -3 always keep image size
+ ATTRIB(Image, zoomBox, float, 0) // used by forcedAspect -2 when the image is larger than the containing box
+ ATTRIB(Image, zoomFactor, float, 1)
+ ATTRIB(Image, zoomOffset, vector, '0.5 0.5 0')
+ ATTRIB(Image, zoomSnapToTheBox, float, 1) // snap the zoomed in image to the box borders when zooming/dragging it
+ ATTRIB(Image, zoomTime, float, 0)
+ ATTRIB(Image, zoomLimitedByTheBox, float, 0) // forbids zoom if image would be larger than the containing box
+ ATTRIB(Image, zoomMax, float, 0)
+ ATTRIB(Image, start_zoomOffset, vector, '0 0 0')
+ ATTRIB(Image, start_coords, vector, '0 0 0')
+ ATTRIB(Image, imgOrigin, vector, '0 0 0')
+ ATTRIB(Image, imgSize, vector, '0 0 0')
+ENDCLASS(Image)
+#endif
+
+#ifdef IMPLEMENTATION
+string Image_toString(entity me)
+{
+ return me.src;
+}
+void Image_configureImage(entity me, string path)
+{
+ me.src = path;
+}
+void Image_initZoom(entity me)
+{
+ me.zoomOffset = '0.5 0.5 0';
+ me.zoomFactor = 1;
+ if (me.forcedAspect == -2)
+ me.zoomBox = -1; // calculate zoomBox at the first updateAspect call
+ if (me.zoomLimitedByTheBox)
+ me.zoomMax = -1; // calculate zoomMax at the first updateAspect call
+}
+
+void Image_draw(entity me)
+{
+ if(me.imgSize_x > 1 || me.imgSize_y > 1)
+ draw_SetClip();
+ draw_Picture(me.imgOrigin, me.src, me.imgSize, me.color, 1);
+ if(me.imgSize_x > 1 || me.imgSize_y > 1)
+ draw_ClearClip();
+ SUPER(Image).draw(me);
+}
+void Image_updateAspect(entity me)
+{
+ float asp = 0;
+ if(me.size_x <= 0 || me.size_y <= 0)
+ return;
+ if(me.forcedAspect == 0)
+ {
+ me.imgOrigin = '0 0 0';
+ me.imgSize = '1 1 0';
+ }
+ else
+ {
+ vector sz = '0 0 0';
+ if(me.forcedAspect < 0)
+ {
+ if (me.src != "")
+ sz = draw_PictureSize(me.src);
+ if(sz_x <= 0 || sz_y <= 0)
+ {
+ // image is broken or doesn't exist, set the size for the placeholder image
+ sz_x = me.size_x;
+ sz_y = me.size_y;
+ }
+ asp = sz_x / sz_y;
+ }
+ else
+ asp = me.forcedAspect;
+
+ if(me.forcedAspect <= -2)
+ {
+ me.imgSize_x = sz_x / me.size_x;
+ me.imgSize_y = sz_y / me.size_y;
+ if(me.zoomBox < 0 && (me.imgSize_x > 1 || me.imgSize_y > 1))
+ {
+ // image larger than the containing box, zoom it out to fit into the box
+ if(me.size_x > asp * me.size_y)
+ me.zoomBox = (me.size_y * asp / me.size_x) / me.imgSize_x;
+ else
+ me.zoomBox = (me.size_x / (asp * me.size_y)) / me.imgSize_y;
+ me.zoomFactor = me.zoomBox;
+ }
+ }
+ else
+ {
+ if(me.size_x > asp * me.size_y)
+ {
+ // x too large, so center x-wise
+ me.imgSize = eY + eX * (me.size_y * asp / me.size_x);
+ }
+ else
+ {
+ // y too large, so center y-wise
+ me.imgSize = eX + eY * (me.size_x / (asp * me.size_y));
+ }
+ }
+ }
+
+ if (me.zoomMax < 0)
+ {
+ if(me.zoomBox > 0)
+ me.zoomMax = me.zoomBox;
+ else
+ {
+ if(me.size_x > asp * me.size_y)
+ me.zoomMax = (me.size_y * asp / me.size_x) / me.imgSize_x;
+ else
+ me.zoomMax = (me.size_x / (asp * me.size_y)) / me.imgSize_y;
+ }
+ }
+
+ if (me.zoomMax > 0 && me.zoomFactor > me.zoomMax)
+ me.zoomFactor = me.zoomMax;
+ if (me.zoomFactor)
+ me.imgSize = me.imgSize * me.zoomFactor;
+
+ if(me.imgSize_x > 1 || me.imgSize_y > 1)
+ {
+ if(me.zoomSnapToTheBox)
+ {
+ if(me.imgSize_x > 1)
+ me.zoomOffset_x = bound(0.5/me.imgSize_x, me.zoomOffset_x, 1 - 0.5/me.imgSize_x);
+ else
+ me.zoomOffset_x = bound(1 - 0.5/me.imgSize_x, me.zoomOffset_x, 0.5/me.imgSize_x);
+
+ if(me.imgSize_y > 1)
+ me.zoomOffset_y = bound(0.5/me.imgSize_y, me.zoomOffset_y, 1 - 0.5/me.imgSize_y);
+ else
+ me.zoomOffset_y = bound(1 - 0.5/me.imgSize_y, me.zoomOffset_y, 0.5/me.imgSize_y);
+ }
+ else
+ {
+ me.zoomOffset_x = bound(0, me.zoomOffset_x, 1);
+ me.zoomOffset_y = bound(0, me.zoomOffset_y, 1);
+ }
+ }
+ else
+ me.zoomOffset = '0.5 0.5 0';
+
+ me.imgOrigin_x = 0.5 - me.zoomOffset_x * me.imgSize_x;
+ me.imgOrigin_y = 0.5 - me.zoomOffset_y * me.imgSize_y;
+}
+float Image_drag_setStartPos(entity me, vector coords)
+{
+ //if(me.imgSize_x > 1 || me.imgSize_y > 1) // check disabled: mousewheel zoom may start from a non-zoomed-in image
+ {
+ me.start_zoomOffset = me.zoomOffset;
+ me.start_coords = coords;
+ }
+ return 1;
+}
+float Image_drag(entity me, vector coords)
+{
+ if(me.imgSize_x > 1 || me.imgSize_y > 1)
+ {
+ me.zoomOffset_x = me.start_zoomOffset_x + (me.start_coords_x - coords_x) / me.imgSize_x;
+ me.zoomOffset_y = me.start_zoomOffset_y + (me.start_coords_y - coords_y) / me.imgSize_y;
+ me.updateAspect(me);
+ }
+ return 1;
+}
+void Image_setZoom(entity me, float z, float atMousePosition)
+{
+ float prev_zoomFactor;
+ prev_zoomFactor = me.zoomFactor;
+ if (z < 0) // multiply by the current zoomFactor (but can also snap to real dimensions or to box)
+ {
+ me.zoomFactor *= -z;
+ float realSize_in_the_middle, boxSize_in_the_middle;
+ realSize_in_the_middle = ((prev_zoomFactor - 1) * (me.zoomFactor - 1) < 0);
+ boxSize_in_the_middle = (me.zoomBox > 0 && (prev_zoomFactor - me.zoomBox) * (me.zoomFactor - me.zoomBox) < 0);
+ if (realSize_in_the_middle && boxSize_in_the_middle)
+ {
+ // snap to real dimensions or to box
+ if (prev_zoomFactor < me.zoomFactor)
+ me.zoomFactor = min(1, me.zoomBox);
+ else
+ me.zoomFactor = max(1, me.zoomBox);
+ }
+ else if (realSize_in_the_middle)
+ me.zoomFactor = 1; // snap to real dimensions
+ else if (boxSize_in_the_middle)
+ me.zoomFactor = me.zoomBox; // snap to box
+ }
+ else if (z == 0) // reset (no zoom)
+ {
+ if (me.zoomBox > 0)
+ me.zoomFactor = me.zoomBox;
+ else
+ me.zoomFactor = 1;
+ }
+ else // directly set
+ me.zoomFactor = z;
+ me.zoomFactor = bound(1/16, me.zoomFactor, 16);
+ if (me.zoomMax > 0 && me.zoomFactor > me.zoomMax)
+ me.zoomFactor = me.zoomMax;
+ if (prev_zoomFactor != me.zoomFactor)
+ {
+ me.zoomTime = time;
+ if (atMousePosition)
+ {
+ me.zoomOffset_x = me.start_zoomOffset_x + (me.start_coords_x - 0.5) / me.imgSize_x;
+ me.zoomOffset_y = me.start_zoomOffset_y + (me.start_coords_y - 0.5) / me.imgSize_y;
+ // updateAspect will reset zoomOffset to '0.5 0.5 0' if
+ // with this zoomFactor the image will not be zoomed in
+ // (updateAspect will check the new values of imgSize).
+ }
+ }
+ me.updateAspect(me);
+}
+void Image_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ SUPER(Image).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+ me.updateAspect(me);
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(InputBox) EXTENDS(Label)
- METHOD(InputBox, configureInputBox, void(entity, string, float, float, string))
- METHOD(InputBox, draw, void(entity))
- METHOD(InputBox, setText, void(entity, string))
- METHOD(InputBox, enterText, void(entity, string))
- METHOD(InputBox, keyDown, float(entity, float, float, float))
- METHOD(InputBox, mouseMove, float(entity, vector))
- METHOD(InputBox, mouseRelease, float(entity, vector))
- METHOD(InputBox, mousePress, float(entity, vector))
- METHOD(InputBox, mouseDrag, float(entity, vector))
- METHOD(InputBox, showNotify, void(entity))
- METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector))
-
- ATTRIB(InputBox, src, string, string_null)
-
- ATTRIB(InputBox, cursorPos, float, 0) // characters
- ATTRIB(InputBox, scrollPos, float, 0) // widths
-
- ATTRIB(InputBox, focusable, float, 1)
- ATTRIB(InputBox, disabled, float, 0)
- ATTRIB(InputBox, lastChangeTime, float, 0)
- ATTRIB(InputBox, dragScrollTimer, float, 0)
- ATTRIB(InputBox, dragScrollPos, vector, '0 0 0')
- ATTRIB(InputBox, pressed, float, 0)
- ATTRIB(InputBox, editColorCodes, float, 1)
- ATTRIB(InputBox, forbiddenCharacters, string, "")
- ATTRIB(InputBox, color, vector, '1 1 1')
- ATTRIB(InputBox, colorF, vector, '1 1 1')
- ATTRIB(InputBox, maxLength, float, 255) // if negative, it counts bytes, not chars
-
- ATTRIB(InputBox, enableClearButton, float, 1)
- ATTRIB(InputBox, clearButton, entity, NULL)
- ATTRIB(InputBox, cb_width, float, 0)
- ATTRIB(InputBox, cb_pressed, float, 0)
- ATTRIB(InputBox, cb_focused, float, 0)
- ATTRIB(InputBox, cb_color, vector, '1 1 1')
- ATTRIB(InputBox, cb_colorF, vector, '1 1 1')
- ATTRIB(InputBox, cb_colorC, vector, '1 1 1')
-ENDCLASS(InputBox)
-void InputBox_Clear_Click(entity btn, entity me);
-#endif
-
-#ifdef IMPLEMENTATION
-void InputBox_configureInputBox(entity me, string theText, float theCursorPos, float theFontSize, string gfx)
-{
- SUPER(InputBox).configureLabel(me, theText, theFontSize, 0.0);
- me.src = gfx;
- me.cursorPos = theCursorPos;
-}
-void InputBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- SUPER(InputBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
- if (me.enableClearButton)
- {
- me.cb_width = absSize_y / absSize_x;
- me.cb_offset = bound(-1, me.cb_offset, 0) * me.cb_width; // bound to range -1, 0
- me.keepspaceRight = me.keepspaceRight - me.cb_offset + me.cb_width;
- }
-}
-
-void InputBox_setText(entity me, string txt)
-{
- if(me.text)
- strunzone(me.text);
- SUPER(InputBox).setText(me, strzone(txt));
-}
-
-void InputBox_Clear_Click(entity btn, entity me)
-{
- me.setText(me, "");
-}
-
-float over_ClearButton(entity me, vector pos)
-{
- if (pos_x >= 1 + me.cb_offset - me.cb_width)
- if (pos_x < 1 + me.cb_offset)
- if (pos_y >= 0)
- if (pos_y < 1)
- return 1;
- return 0;
-}
-
-float InputBox_mouseMove(entity me, vector pos)
-{
- if (me.enableClearButton)
- {
- if (over_ClearButton(me, pos))
- {
- me.cb_focused = 1;
- return 1;
- }
- me.cb_focused = 0;
- }
- return 1;
-}
-
-float InputBox_mouseDrag(entity me, vector pos)
-{
- float p;
- if(me.pressed)
- {
- me.dragScrollPos = pos;
- p = me.scrollPos + pos_x - me.keepspaceLeft;
- me.cursorPos = draw_TextLengthUpToWidth(me.text, p, 0, me.realFontSize);
- me.lastChangeTime = time;
- }
- else if (me.enableClearButton)
- {
- if (over_ClearButton(me, pos))
- {
- me.cb_pressed = 1;
- return 1;
- }
- }
- me.cb_pressed = 0;
- return 1;
-}
-
-float InputBox_mousePress(entity me, vector pos)
-{
- if (me.enableClearButton)
- if (over_ClearButton(me, pos))
- {
- me.cb_pressed = 1;
- return 1;
- }
- me.dragScrollTimer = time;
- me.pressed = 1;
- return InputBox_mouseDrag(me, pos);
-}
-
-float InputBox_mouseRelease(entity me, vector pos)
-{
- if(me.cb_pressed)
- if (over_ClearButton(me, pos))
- {
- me.cb_pressed = 0;
- InputBox_Clear_Click(world, me);
- return 1;
- }
- float r = InputBox_mouseDrag(me, pos);
- //reset cb_pressed after mouseDrag, mouseDrag could set cb_pressed in this case:
- //mouse press out of the clear button, drag and then mouse release over the clear button
- me.cb_pressed = 0;
- me.pressed = 0;
- return r;
-}
-
-void InputBox_enterText(entity me, string ch)
-{
- float i;
- for(i = 0; i < strlen(ch); ++i)
- if(strstrofs(me.forbiddenCharacters, substring(ch, i, 1), 0) > -1)
- return;
- if(me.maxLength > 0)
- {
- if(strlen(ch) + strlen(me.text) > me.maxLength)
- return;
- }
- else if(me.maxLength < 0)
- {
- if(u8_strsize(ch) + u8_strsize(me.text) > -me.maxLength)
- return;
- }
- me.setText(me, strcat(substring(me.text, 0, me.cursorPos), ch, substring(me.text, me.cursorPos, strlen(me.text) - me.cursorPos)));
- me.cursorPos += strlen(ch);
-}
-
-float InputBox_keyDown(entity me, float key, float ascii, float shift)
-{
- me.lastChangeTime = time;
- me.dragScrollTimer = time;
- if(ascii >= 32 && ascii != 127)
- {
- me.enterText(me, chr(ascii));
- return 1;
- }
- switch(key)
- {
- case K_KP_LEFTARROW:
- case K_LEFTARROW:
- me.cursorPos -= 1;
- return 1;
- case K_KP_RIGHTARROW:
- case K_RIGHTARROW:
- me.cursorPos += 1;
- return 1;
- case K_KP_HOME:
- case K_HOME:
- me.cursorPos = 0;
- return 1;
- case K_KP_END:
- case K_END:
- me.cursorPos = strlen(me.text);
- return 1;
- case K_BACKSPACE:
- if(me.cursorPos > 0)
- {
- me.cursorPos -= 1;
- me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
- }
- return 1;
- case K_KP_DEL:
- case K_DEL:
- if(shift & S_CTRL)
- me.setText(me, "");
- else
- me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
- return 1;
- }
- return 0;
-}
-
-void InputBox_draw(entity me)
-{
- string CURSOR = "_";
- float cursorPosInWidths, totalSizeInWidths;
-
- if(me.pressed)
- me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event
-
- if(me.recalcPos)
- me.recalcPositionWithText(me, me.text);
-
- me.focusable = !me.disabled;
- if(me.disabled)
- draw_alpha *= me.disabledAlpha;
-
- if(me.src)
- {
- if(me.focused && !me.disabled)
- draw_ButtonPicture('0 0 0', strcat(me.src, "_f"), '1 1 0', me.colorF, 1);
- else
- draw_ButtonPicture('0 0 0', strcat(me.src, "_n"), '1 1 0', me.color, 1);
- }
-
- me.cursorPos = bound(0, me.cursorPos, strlen(me.text));
- cursorPosInWidths = draw_TextWidth(substring(me.text, 0, me.cursorPos), 0, me.realFontSize);
- totalSizeInWidths = draw_TextWidth(strcat(me.text, CURSOR), 0, me.realFontSize);
-
- if(me.dragScrollTimer < time)
- {
- float save;
- save = me.scrollPos;
- me.scrollPos = bound(cursorPosInWidths - (0.875 - me.keepspaceLeft - me.keepspaceRight), me.scrollPos, cursorPosInWidths - 0.125);
- if(me.scrollPos != save)
- me.dragScrollTimer = time + 0.2;
- }
- me.scrollPos = min(me.scrollPos, totalSizeInWidths - (1 - me.keepspaceRight - me.keepspaceLeft));
- me.scrollPos = max(0, me.scrollPos);
-
- draw_SetClipRect(eX * me.keepspaceLeft, eX * (1 - me.keepspaceLeft - me.keepspaceRight) + eY);
- if(me.editColorCodes)
- {
- string ch, ch2;
- float i, n;
- vector theColor;
- float theAlpha; //float theVariableAlpha;
- vector p;
- vector theTempColor;
- float component;
-
- p = me.realOrigin - eX * me.scrollPos;
- theColor = '1 1 1';
- theAlpha = 1; //theVariableAlpha = 1; // changes when ^ax found
-
- n = strlen(me.text);
- for(i = 0; i < n; ++i)
- {
- ch = substring(me.text, i, 1);
- if(ch == "^")
- {
- float w;
- ch2 = substring(me.text, i+1, 1);
- w = draw_TextWidth(strcat(ch, ch2), 0, me.realFontSize);
- if(ch2 == "^")
- {
- draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
- draw_Text(p + eX * 0.25 * w, "^", me.realFontSize, theColor, theAlpha, 0);
- }
- else if(ch2 == "0" || stof(ch2)) // digit?
- {
- switch(stof(ch2))
- {
- case 0: theColor = '0 0 0'; theAlpha = 1; break;
- case 1: theColor = '1 0 0'; theAlpha = 1; break;
- case 2: theColor = '0 1 0'; theAlpha = 1; break;
- case 3: theColor = '1 1 0'; theAlpha = 1; break;
- case 4: theColor = '0 0 1'; theAlpha = 1; break;
- case 5: theColor = '0 1 1'; theAlpha = 1; break;
- case 6: theColor = '1 0 1'; theAlpha = 1; break;
- case 7: theColor = '1 1 1'; theAlpha = 1; break;
- case 8: theColor = '1 1 1'; theAlpha = 0.5; break;
- case 9: theColor = '0.5 0.5 0.5'; theAlpha = 1; break;
- }
- draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
- draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
- }
- else if(ch2 == "x") // ^x found
- {
- theColor = '1 1 1';
-
- component = HEXDIGIT_TO_DEC(substring(me.text, i+2, 1));
- if (component >= 0) // ^xr found
- {
- theTempColor_x = component/15;
-
- component = HEXDIGIT_TO_DEC(substring(me.text, i+3, 1));
- if (component >= 0) // ^xrg found
- {
- theTempColor_y = component/15;
-
- component = HEXDIGIT_TO_DEC(substring(me.text, i+4, 1));
- if (component >= 0) // ^xrgb found
- {
- theTempColor_z = component/15;
- theColor = theTempColor;
- w = draw_TextWidth(substring(me.text, i, 5), 0, me.realFontSize);
-
- draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
- draw_Text(p, substring(me.text, i, 5), me.realFontSize, theColor, 1, 0); // theVariableAlpha instead of 1 using alpha tags ^ax
- i += 3;
- }
- else
- {
- // blue missing
- w = draw_TextWidth(substring(me.text, i, 4), 0, me.realFontSize);
- draw_Fill(p, eX * w + eY * me.realFontSize_y, eZ, 0.5);
- draw_Text(p, substring(me.text, i, 4), me.realFontSize, '1 1 1', theAlpha, 0);
- i += 2;
- }
- }
- else
- {
- // green missing
- w = draw_TextWidth(substring(me.text, i, 3), 0, me.realFontSize);
- draw_Fill(p, eX * w + eY * me.realFontSize_y, eY, 0.5);
- draw_Text(p, substring(me.text, i, 3), me.realFontSize, '1 1 1', theAlpha, 0);
- i += 1;
- }
- }
- else
- {
- // red missing
- //w = draw_TextWidth(substring(me.text, i, 2), 0) * me.realFontSize_x;
- draw_Fill(p, eX * w + eY * me.realFontSize_y, eX, 0.5);
- draw_Text(p, substring(me.text, i, 2), me.realFontSize, '1 1 1', theAlpha, 0);
- }
- }
- else
- {
- draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
- draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
- }
- p += w * eX;
- ++i;
- continue;
- }
- draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0); // TODO theVariableAlpha
- p += eX * draw_TextWidth(ch, 0, me.realFontSize);
- }
- }
- else
- draw_Text(me.realOrigin - eX * me.scrollPos, me.text, me.realFontSize, '1 1 1', 1, 0);
-
- if(!me.focused || (time - me.lastChangeTime) < floor(time - me.lastChangeTime) + 0.5)
- draw_Text(me.realOrigin + eX * (cursorPosInWidths - me.scrollPos), CURSOR, me.realFontSize, '1 1 1', 1, 0);
-
- draw_ClearClip();
-
- if (me.enableClearButton)
- if (me.text != "")
- {
- if(me.focused && me.cb_pressed)
- draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_c"), eX * me.cb_width + eY, me.cb_colorC, 1);
- else if(me.focused && me.cb_focused)
- draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_f"), eX * me.cb_width + eY, me.cb_colorF, 1);
- else
- draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_n"), eX * me.cb_width + eY, me.cb_color, 1);
- }
-
- // skipping SUPER(InputBox).draw(me);
- Item_draw(me);
-}
-
-void InputBox_showNotify(entity me)
-{
- me.focusable = !me.disabled;
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(InputBox) EXTENDS(Label)
+ METHOD(InputBox, configureInputBox, void(entity, string, float, float, string))
+ METHOD(InputBox, draw, void(entity))
+ METHOD(InputBox, setText, void(entity, string))
+ METHOD(InputBox, enterText, void(entity, string))
+ METHOD(InputBox, keyDown, float(entity, float, float, float))
+ METHOD(InputBox, mouseMove, float(entity, vector))
+ METHOD(InputBox, mouseRelease, float(entity, vector))
+ METHOD(InputBox, mousePress, float(entity, vector))
+ METHOD(InputBox, mouseDrag, float(entity, vector))
+ METHOD(InputBox, showNotify, void(entity))
+ METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector))
+
+ ATTRIB(InputBox, src, string, string_null)
+
+ ATTRIB(InputBox, cursorPos, float, 0) // characters
+ ATTRIB(InputBox, scrollPos, float, 0) // widths
+
+ ATTRIB(InputBox, focusable, float, 1)
+ ATTRIB(InputBox, disabled, float, 0)
+ ATTRIB(InputBox, lastChangeTime, float, 0)
+ ATTRIB(InputBox, dragScrollTimer, float, 0)
+ ATTRIB(InputBox, dragScrollPos, vector, '0 0 0')
+ ATTRIB(InputBox, pressed, float, 0)
+ ATTRIB(InputBox, editColorCodes, float, 1)
+ ATTRIB(InputBox, forbiddenCharacters, string, "")
+ ATTRIB(InputBox, color, vector, '1 1 1')
+ ATTRIB(InputBox, colorF, vector, '1 1 1')
+ ATTRIB(InputBox, maxLength, float, 255) // if negative, it counts bytes, not chars
+
+ ATTRIB(InputBox, enableClearButton, float, 1)
+ ATTRIB(InputBox, clearButton, entity, NULL)
+ ATTRIB(InputBox, cb_width, float, 0)
+ ATTRIB(InputBox, cb_pressed, float, 0)
+ ATTRIB(InputBox, cb_focused, float, 0)
+ ATTRIB(InputBox, cb_color, vector, '1 1 1')
+ ATTRIB(InputBox, cb_colorF, vector, '1 1 1')
+ ATTRIB(InputBox, cb_colorC, vector, '1 1 1')
+ENDCLASS(InputBox)
+void InputBox_Clear_Click(entity btn, entity me);
+#endif
+
+#ifdef IMPLEMENTATION
+void InputBox_configureInputBox(entity me, string theText, float theCursorPos, float theFontSize, string gfx)
+{
+ SUPER(InputBox).configureLabel(me, theText, theFontSize, 0.0);
+ me.src = gfx;
+ me.cursorPos = theCursorPos;
+}
+void InputBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ SUPER(InputBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+ if (me.enableClearButton)
+ {
+ me.cb_width = absSize_y / absSize_x;
+ me.cb_offset = bound(-1, me.cb_offset, 0) * me.cb_width; // bound to range -1, 0
+ me.keepspaceRight = me.keepspaceRight - me.cb_offset + me.cb_width;
+ }
+}
+
+void InputBox_setText(entity me, string txt)
+{
+ if(me.text)
+ strunzone(me.text);
+ SUPER(InputBox).setText(me, strzone(txt));
+}
+
+void InputBox_Clear_Click(entity btn, entity me)
+{
+ me.setText(me, "");
+}
+
+float over_ClearButton(entity me, vector pos)
+{
+ if (pos_x >= 1 + me.cb_offset - me.cb_width)
+ if (pos_x < 1 + me.cb_offset)
+ if (pos_y >= 0)
+ if (pos_y < 1)
+ return 1;
+ return 0;
+}
+
+float InputBox_mouseMove(entity me, vector pos)
+{
+ if (me.enableClearButton)
+ {
+ if (over_ClearButton(me, pos))
+ {
+ me.cb_focused = 1;
+ return 1;
+ }
+ me.cb_focused = 0;
+ }
+ return 1;
+}
+
+float InputBox_mouseDrag(entity me, vector pos)
+{
+ float p;
+ if(me.pressed)
+ {
+ me.dragScrollPos = pos;
+ p = me.scrollPos + pos_x - me.keepspaceLeft;
+ me.cursorPos = draw_TextLengthUpToWidth(me.text, p, 0, me.realFontSize);
+ me.lastChangeTime = time;
+ }
+ else if (me.enableClearButton)
+ {
+ if (over_ClearButton(me, pos))
+ {
+ me.cb_pressed = 1;
+ return 1;
+ }
+ }
+ me.cb_pressed = 0;
+ return 1;
+}
+
+float InputBox_mousePress(entity me, vector pos)
+{
+ if (me.enableClearButton)
+ if (over_ClearButton(me, pos))
+ {
+ me.cb_pressed = 1;
+ return 1;
+ }
+ me.dragScrollTimer = time;
+ me.pressed = 1;
+ return InputBox_mouseDrag(me, pos);
+}
+
+float InputBox_mouseRelease(entity me, vector pos)
+{
+ if(me.cb_pressed)
+ if (over_ClearButton(me, pos))
+ {
+ me.cb_pressed = 0;
+ InputBox_Clear_Click(world, me);
+ return 1;
+ }
+ float r = InputBox_mouseDrag(me, pos);
+ //reset cb_pressed after mouseDrag, mouseDrag could set cb_pressed in this case:
+ //mouse press out of the clear button, drag and then mouse release over the clear button
+ me.cb_pressed = 0;
+ me.pressed = 0;
+ return r;
+}
+
+void InputBox_enterText(entity me, string ch)
+{
+ float i;
+ for(i = 0; i < strlen(ch); ++i)
+ if(strstrofs(me.forbiddenCharacters, substring(ch, i, 1), 0) > -1)
+ return;
+ if(me.maxLength > 0)
+ {
+ if(strlen(ch) + strlen(me.text) > me.maxLength)
+ return;
+ }
+ else if(me.maxLength < 0)
+ {
+ if(u8_strsize(ch) + u8_strsize(me.text) > -me.maxLength)
+ return;
+ }
+ me.setText(me, strcat(substring(me.text, 0, me.cursorPos), ch, substring(me.text, me.cursorPos, strlen(me.text) - me.cursorPos)));
+ me.cursorPos += strlen(ch);
+}
+
+float InputBox_keyDown(entity me, float key, float ascii, float shift)
+{
+ me.lastChangeTime = time;
+ me.dragScrollTimer = time;
+ if(ascii >= 32 && ascii != 127)
+ {
+ me.enterText(me, chr(ascii));
+ return 1;
+ }
+ switch(key)
+ {
+ case K_KP_LEFTARROW:
+ case K_LEFTARROW:
+ me.cursorPos -= 1;
+ return 1;
+ case K_KP_RIGHTARROW:
+ case K_RIGHTARROW:
+ me.cursorPos += 1;
+ return 1;
+ case K_KP_HOME:
+ case K_HOME:
+ me.cursorPos = 0;
+ return 1;
+ case K_KP_END:
+ case K_END:
+ me.cursorPos = strlen(me.text);
+ return 1;
+ case K_BACKSPACE:
+ if(me.cursorPos > 0)
+ {
+ me.cursorPos -= 1;
+ me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
+ }
+ return 1;
+ case K_KP_DEL:
+ case K_DEL:
+ if(shift & S_CTRL)
+ me.setText(me, "");
+ else
+ me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
+ return 1;
+ }
+ return 0;
+}
+
+void InputBox_draw(entity me)
+{
+ string CURSOR = "_";
+ float cursorPosInWidths, totalSizeInWidths;
+
+ if(me.pressed)
+ me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event
+
+ if(me.recalcPos)
+ me.recalcPositionWithText(me, me.text);
+
+ me.focusable = !me.disabled;
+ if(me.disabled)
+ draw_alpha *= me.disabledAlpha;
+
+ if(me.src)
+ {
+ if(me.focused && !me.disabled)
+ draw_ButtonPicture('0 0 0', strcat(me.src, "_f"), '1 1 0', me.colorF, 1);
+ else
+ draw_ButtonPicture('0 0 0', strcat(me.src, "_n"), '1 1 0', me.color, 1);
+ }
+
+ me.cursorPos = bound(0, me.cursorPos, strlen(me.text));
+ cursorPosInWidths = draw_TextWidth(substring(me.text, 0, me.cursorPos), 0, me.realFontSize);
+ totalSizeInWidths = draw_TextWidth(strcat(me.text, CURSOR), 0, me.realFontSize);
+
+ if(me.dragScrollTimer < time)
+ {
+ float save;
+ save = me.scrollPos;
+ me.scrollPos = bound(cursorPosInWidths - (0.875 - me.keepspaceLeft - me.keepspaceRight), me.scrollPos, cursorPosInWidths - 0.125);
+ if(me.scrollPos != save)
+ me.dragScrollTimer = time + 0.2;
+ }
+ me.scrollPos = min(me.scrollPos, totalSizeInWidths - (1 - me.keepspaceRight - me.keepspaceLeft));
+ me.scrollPos = max(0, me.scrollPos);
+
+ draw_SetClipRect(eX * me.keepspaceLeft, eX * (1 - me.keepspaceLeft - me.keepspaceRight) + eY);
+ if(me.editColorCodes)
+ {
+ string ch, ch2;
+ float i, n;
+ vector theColor;
+ float theAlpha; //float theVariableAlpha;
+ vector p;
+ vector theTempColor;
+ float component;
+
+ p = me.realOrigin - eX * me.scrollPos;
+ theColor = '1 1 1';
+ theAlpha = 1; //theVariableAlpha = 1; // changes when ^ax found
+
+ n = strlen(me.text);
+ for(i = 0; i < n; ++i)
+ {
+ ch = substring(me.text, i, 1);
+ if(ch == "^")
+ {
+ float w;
+ ch2 = substring(me.text, i+1, 1);
+ w = draw_TextWidth(strcat(ch, ch2), 0, me.realFontSize);
+ if(ch2 == "^")
+ {
+ draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
+ draw_Text(p + eX * 0.25 * w, "^", me.realFontSize, theColor, theAlpha, 0);
+ }
+ else if(ch2 == "0" || stof(ch2)) // digit?
+ {
+ switch(stof(ch2))
+ {
+ case 0: theColor = '0 0 0'; theAlpha = 1; break;
+ case 1: theColor = '1 0 0'; theAlpha = 1; break;
+ case 2: theColor = '0 1 0'; theAlpha = 1; break;
+ case 3: theColor = '1 1 0'; theAlpha = 1; break;
+ case 4: theColor = '0 0 1'; theAlpha = 1; break;
+ case 5: theColor = '0 1 1'; theAlpha = 1; break;
+ case 6: theColor = '1 0 1'; theAlpha = 1; break;
+ case 7: theColor = '1 1 1'; theAlpha = 1; break;
+ case 8: theColor = '1 1 1'; theAlpha = 0.5; break;
+ case 9: theColor = '0.5 0.5 0.5'; theAlpha = 1; break;
+ }
+ draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
+ draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
+ }
+ else if(ch2 == "x") // ^x found
+ {
+ theColor = '1 1 1';
+
+ component = HEXDIGIT_TO_DEC(substring(me.text, i+2, 1));
+ if (component >= 0) // ^xr found
+ {
+ theTempColor_x = component/15;
+
+ component = HEXDIGIT_TO_DEC(substring(me.text, i+3, 1));
+ if (component >= 0) // ^xrg found
+ {
+ theTempColor_y = component/15;
+
+ component = HEXDIGIT_TO_DEC(substring(me.text, i+4, 1));
+ if (component >= 0) // ^xrgb found
+ {
+ theTempColor_z = component/15;
+ theColor = theTempColor;
+ w = draw_TextWidth(substring(me.text, i, 5), 0, me.realFontSize);
+
+ draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
+ draw_Text(p, substring(me.text, i, 5), me.realFontSize, theColor, 1, 0); // theVariableAlpha instead of 1 using alpha tags ^ax
+ i += 3;
+ }
+ else
+ {
+ // blue missing
+ w = draw_TextWidth(substring(me.text, i, 4), 0, me.realFontSize);
+ draw_Fill(p, eX * w + eY * me.realFontSize_y, eZ, 0.5);
+ draw_Text(p, substring(me.text, i, 4), me.realFontSize, '1 1 1', theAlpha, 0);
+ i += 2;
+ }
+ }
+ else
+ {
+ // green missing
+ w = draw_TextWidth(substring(me.text, i, 3), 0, me.realFontSize);
+ draw_Fill(p, eX * w + eY * me.realFontSize_y, eY, 0.5);
+ draw_Text(p, substring(me.text, i, 3), me.realFontSize, '1 1 1', theAlpha, 0);
+ i += 1;
+ }
+ }
+ else
+ {
+ // red missing
+ //w = draw_TextWidth(substring(me.text, i, 2), 0) * me.realFontSize_x;
+ draw_Fill(p, eX * w + eY * me.realFontSize_y, eX, 0.5);
+ draw_Text(p, substring(me.text, i, 2), me.realFontSize, '1 1 1', theAlpha, 0);
+ }
+ }
+ else
+ {
+ draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
+ draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
+ }
+ p += w * eX;
+ ++i;
+ continue;
+ }
+ draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0); // TODO theVariableAlpha
+ p += eX * draw_TextWidth(ch, 0, me.realFontSize);
+ }
+ }
+ else
+ draw_Text(me.realOrigin - eX * me.scrollPos, me.text, me.realFontSize, '1 1 1', 1, 0);
+
+ if(!me.focused || (time - me.lastChangeTime) < floor(time - me.lastChangeTime) + 0.5)
+ draw_Text(me.realOrigin + eX * (cursorPosInWidths - me.scrollPos), CURSOR, me.realFontSize, '1 1 1', 1, 0);
+
+ draw_ClearClip();
+
+ if (me.enableClearButton)
+ if (me.text != "")
+ {
+ if(me.focused && me.cb_pressed)
+ draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_c"), eX * me.cb_width + eY, me.cb_colorC, 1);
+ else if(me.focused && me.cb_focused)
+ draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_f"), eX * me.cb_width + eY, me.cb_colorF, 1);
+ else
+ draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_n"), eX * me.cb_width + eY, me.cb_color, 1);
+ }
+
+ // skipping SUPER(InputBox).draw(me);
+ Item_draw(me);
+}
+
+void InputBox_showNotify(entity me)
+{
+ me.focusable = !me.disabled;
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(InputContainer) EXTENDS(Container)
- METHOD(InputContainer, keyDown, float(entity, float, float, float))
- METHOD(InputContainer, mouseMove, float(entity, vector))
- METHOD(InputContainer, mousePress, float(entity, vector))
- METHOD(InputContainer, mouseRelease, float(entity, vector))
- METHOD(InputContainer, mouseDrag, float(entity, vector))
- METHOD(InputContainer, focusLeave, void(entity))
- METHOD(InputContainer, resizeNotify, void(entity, vector, vector, vector, vector))
-
- METHOD(InputContainer, _changeFocusXY, float(entity, vector))
- ATTRIB(InputContainer, mouseFocusedChild, entity, NULL)
- ATTRIB(InputContainer, isTabRoot, float, 0)
-ENDCLASS(InputContainer)
-#endif
-
-#ifdef IMPLEMENTATION
-void InputContainer_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- SUPER(InputContainer).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
- /*
- if(me.parent.instanceOfInputContainer)
- me.isTabRoot = 0;
- else
- me.isTabRoot = 1;
- */
-}
-
-void InputContainer_focusLeave(entity me)
-{
- SUPER(InputContainer).focusLeave(me);
- me.mouseFocusedChild = NULL;
-}
-
-float InputContainer_keyDown(entity me, float scan, float ascii, float shift)
-{
- entity f, ff;
- if(SUPER(InputContainer).keyDown(me, scan, ascii, shift))
- return 1;
- if(scan == K_ESCAPE)
- {
- f = me.focusedChild;
- if(f)
- {
- me.setFocus(me, NULL);
- return 1;
- }
- return 0;
- }
- if(scan == K_TAB)
- {
- f = me.focusedChild;
- if(shift & S_SHIFT)
- {
- if(f)
- {
- for(ff = f.prevSibling; ff; ff = ff.prevSibling)
- {
- if (!ff.focusable)
- continue;
- me.setFocus(me, ff);
- return 1;
- }
- }
- if(!f || me.isTabRoot)
- {
- for(ff = me.lastChild; ff; ff = ff.prevSibling)
- {
- if (!ff.focusable)
- continue;
- me.setFocus(me, ff);
- return 1;
- }
- return 0; // AIIIIEEEEE!
- }
- }
- else
- {
- if(f)
- {
- for(ff = f.nextSibling; ff; ff = ff.nextSibling)
- {
- if (!ff.focusable)
- continue;
- me.setFocus(me, ff);
- return 1;
- }
- }
- if(!f || me.isTabRoot)
- {
- for(ff = me.firstChild; ff; ff = ff.nextSibling)
- {
- if (!ff.focusable)
- continue;
- me.setFocus(me, ff);
- return 1;
- }
- return 0; // AIIIIEEEEE!
- }
- }
- }
- return 0;
-}
-
-float InputContainer__changeFocusXY(entity me, vector pos)
-{
- entity e, ne;
- e = me.mouseFocusedChild;
- ne = me.itemFromPoint(me, pos);
- if(ne)
- if (!ne.focusable)
- ne = NULL;
- me.mouseFocusedChild = ne;
- if(ne)
- if(ne != e)
- {
- me.setFocus(me, ne);
- if(ne.instanceOfInputContainer)
- {
- ne.focusedChild = NULL;
- ne._changeFocusXY(e, globalToBox(pos, ne.Container_origin, ne.Container_size));
- }
- }
- return (ne != NULL);
-}
-
-float InputContainer_mouseDrag(entity me, vector pos)
-{
- if(SUPER(InputContainer).mouseDrag(me, pos))
- return 1;
- if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
- return 1;
- return 0;
-}
-float InputContainer_mouseMove(entity me, vector pos)
-{
- if(me.mouseFocusedChild != me.focusedChild) // if the keyboard moved the focus away
- me.mouseFocusedChild = NULL; // force focusing
- if(me._changeFocusXY(me, pos))
- if(SUPER(InputContainer).mouseMove(me, pos))
- return 1;
- if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
- return 1;
- return 0;
-}
-float InputContainer_mousePress(entity me, vector pos)
-{
- me.mouseFocusedChild = NULL; // force focusing
- if(me._changeFocusXY(me, pos))
- if(SUPER(InputContainer).mousePress(me, pos))
- return 1;
- if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
- return 1;
- return 0;
-}
-float InputContainer_mouseRelease(entity me, vector pos)
-{
- SUPER(InputContainer).mouseRelease(me, pos); // return value?
- if(me.focused) // am I still eligible for this? (UGLY HACK, but a mouse event could have changed focus away)
- if(me._changeFocusXY(me, pos))
- return 1;
- if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
- return 1;
- return 0;
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(InputContainer) EXTENDS(Container)
+ METHOD(InputContainer, keyDown, float(entity, float, float, float))
+ METHOD(InputContainer, mouseMove, float(entity, vector))
+ METHOD(InputContainer, mousePress, float(entity, vector))
+ METHOD(InputContainer, mouseRelease, float(entity, vector))
+ METHOD(InputContainer, mouseDrag, float(entity, vector))
+ METHOD(InputContainer, focusLeave, void(entity))
+ METHOD(InputContainer, resizeNotify, void(entity, vector, vector, vector, vector))
+
+ METHOD(InputContainer, _changeFocusXY, float(entity, vector))
+ ATTRIB(InputContainer, mouseFocusedChild, entity, NULL)
+ ATTRIB(InputContainer, isTabRoot, float, 0)
+ENDCLASS(InputContainer)
+#endif
+
+#ifdef IMPLEMENTATION
+void InputContainer_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ SUPER(InputContainer).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+ /*
+ if(me.parent.instanceOfInputContainer)
+ me.isTabRoot = 0;
+ else
+ me.isTabRoot = 1;
+ */
+}
+
+void InputContainer_focusLeave(entity me)
+{
+ SUPER(InputContainer).focusLeave(me);
+ me.mouseFocusedChild = NULL;
+}
+
+float InputContainer_keyDown(entity me, float scan, float ascii, float shift)
+{
+ entity f, ff;
+ if(SUPER(InputContainer).keyDown(me, scan, ascii, shift))
+ return 1;
+ if(scan == K_ESCAPE)
+ {
+ f = me.focusedChild;
+ if(f)
+ {
+ me.setFocus(me, NULL);
+ return 1;
+ }
+ return 0;
+ }
+ if(scan == K_TAB)
+ {
+ f = me.focusedChild;
+ if(shift & S_SHIFT)
+ {
+ if(f)
+ {
+ for(ff = f.prevSibling; ff; ff = ff.prevSibling)
+ {
+ if (!ff.focusable)
+ continue;
+ me.setFocus(me, ff);
+ return 1;
+ }
+ }
+ if(!f || me.isTabRoot)
+ {
+ for(ff = me.lastChild; ff; ff = ff.prevSibling)
+ {
+ if (!ff.focusable)
+ continue;
+ me.setFocus(me, ff);
+ return 1;
+ }
+ return 0; // AIIIIEEEEE!
+ }
+ }
+ else
+ {
+ if(f)
+ {
+ for(ff = f.nextSibling; ff; ff = ff.nextSibling)
+ {
+ if (!ff.focusable)
+ continue;
+ me.setFocus(me, ff);
+ return 1;
+ }
+ }
+ if(!f || me.isTabRoot)
+ {
+ for(ff = me.firstChild; ff; ff = ff.nextSibling)
+ {
+ if (!ff.focusable)
+ continue;
+ me.setFocus(me, ff);
+ return 1;
+ }
+ return 0; // AIIIIEEEEE!
+ }
+ }
+ }
+ return 0;
+}
+
+float InputContainer__changeFocusXY(entity me, vector pos)
+{
+ entity e, ne;
+ e = me.mouseFocusedChild;
+ ne = me.itemFromPoint(me, pos);
+ if(ne)
+ if (!ne.focusable)
+ ne = NULL;
+ me.mouseFocusedChild = ne;
+ if(ne)
+ if(ne != e)
+ {
+ me.setFocus(me, ne);
+ if(ne.instanceOfInputContainer)
+ {
+ ne.focusedChild = NULL;
+ ne._changeFocusXY(e, globalToBox(pos, ne.Container_origin, ne.Container_size));
+ }
+ }
+ return (ne != NULL);
+}
+
+float InputContainer_mouseDrag(entity me, vector pos)
+{
+ if(SUPER(InputContainer).mouseDrag(me, pos))
+ return 1;
+ if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
+ return 1;
+ return 0;
+}
+float InputContainer_mouseMove(entity me, vector pos)
+{
+ if(me.mouseFocusedChild != me.focusedChild) // if the keyboard moved the focus away
+ me.mouseFocusedChild = NULL; // force focusing
+ if(me._changeFocusXY(me, pos))
+ if(SUPER(InputContainer).mouseMove(me, pos))
+ return 1;
+ if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
+ return 1;
+ return 0;
+}
+float InputContainer_mousePress(entity me, vector pos)
+{
+ me.mouseFocusedChild = NULL; // force focusing
+ if(me._changeFocusXY(me, pos))
+ if(SUPER(InputContainer).mousePress(me, pos))
+ return 1;
+ if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
+ return 1;
+ return 0;
+}
+float InputContainer_mouseRelease(entity me, vector pos)
+{
+ SUPER(InputContainer).mouseRelease(me, pos); // return value?
+ if(me.focused) // am I still eligible for this? (UGLY HACK, but a mouse event could have changed focus away)
+ if(me._changeFocusXY(me, pos))
+ return 1;
+ if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
+ return 1;
+ return 0;
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(Label) EXTENDS(Item)
- METHOD(Label, configureLabel, void(entity, string, float, float))
- METHOD(Label, draw, void(entity))
- METHOD(Label, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Label, setText, void(entity, string))
- METHOD(Label, toString, string(entity))
- METHOD(Label, recalcPositionWithText, void(entity, string))
- ATTRIB(Label, isBold, float, 0)
- ATTRIB(Label, text, string, string_null)
- ATTRIB(Label, currentText, string, string_null)
- ATTRIB(Label, fontSize, float, 8)
- ATTRIB(Label, align, float, 0.5)
- ATTRIB(Label, allowCut, float, 0)
- ATTRIB(Label, allowColors, float, 0)
- ATTRIB(Label, keepspaceLeft, float, 0) // for use by subclasses (radiobuttons for example)
- ATTRIB(Label, keepspaceRight, float, 0)
- ATTRIB(Label, marginLeft, float, 0) // alternate way to specify keepspace* (in characters from the font)
- ATTRIB(Label, marginRight, float, 0)
- ATTRIB(Label, realFontSize, vector, '0 0 0')
- ATTRIB(Label, realOrigin, vector, '0 0 0')
- ATTRIB(Label, alpha, float, 0.7)
- ATTRIB(Label, colorL, vector, SKINCOLOR_TEXT)
- ATTRIB(Label, disabled, float, 0)
- ATTRIB(Label, disabledAlpha, float, 0.3)
- ATTRIB(Label, textEntity, entity, NULL)
- ATTRIB(Label, allowWrap, float, 0)
- ATTRIB(Label, recalcPos, float, 0)
- ATTRIB(Label, condenseFactor, float, 1)
- ATTRIB(Label, overrideRealOrigin, vector, '0 0 0')
- ATTRIB(Label, overrideCondenseFactor, float, 0)
-ENDCLASS(Label)
-#endif
-
-#ifdef IMPLEMENTATION
-string Label_toString(entity me)
-{
- return me.text;
-}
-void Label_setText(entity me, string txt)
-{
- me.text = txt;
- if(txt != me.currentText)
- {
- if(me.currentText)
- strunzone(me.currentText);
- me.currentText = strzone(txt);
- me.recalcPos = 1;
- }
-}
-void Label_recalcPositionWithText(entity me, string t)
-{
- float spaceAvail;
- spaceAvail = 1 - me.keepspaceLeft - me.keepspaceRight;
-
- if(me.isBold)
- draw_beginBoldFont();
-
- float spaceUsed;
- spaceUsed = draw_TextWidth(t, me.allowColors, me.realFontSize);
-
- if(spaceUsed <= spaceAvail)
- {
- if(!me.overrideRealOrigin_x)
- me.realOrigin_x = me.align * (spaceAvail - spaceUsed) + me.keepspaceLeft;
- if(!me.overrideCondenseFactor)
- me.condenseFactor = 1;
- }
- else if(me.allowCut || me.allowWrap)
- {
- if(!me.overrideRealOrigin_x)
- me.realOrigin_x = me.keepspaceLeft;
- if(!me.overrideCondenseFactor)
- me.condenseFactor = 1;
- }
- else
- {
- if(!me.overrideRealOrigin_x)
- me.realOrigin_x = me.keepspaceLeft;
- if(!me.overrideCondenseFactor)
- me.condenseFactor = spaceAvail / spaceUsed;
- dprintf("NOTE: label text %s too wide for label, condensed by factor %f\n", t, me.condenseFactor);
- }
-
- if(!me.overrideRealOrigin_y)
- {
- float lines;
- vector dfs;
- vector fs;
-
- // set up variables to draw in condensed size, but use hinting for original size
- fs = me.realFontSize;
- fs_x *= me.condenseFactor;
-
- dfs = draw_fontscale;
- draw_fontscale_x *= me.condenseFactor;
-
- if(me.allowCut) // FIXME allowCut incompatible with align != 0
- lines = 1;
- else if(me.allowWrap) // FIXME allowWrap incompatible with align != 0
- {
- getWrappedLine_remaining = me.text;
- lines = 0;
- while(getWrappedLine_remaining)
- {
- if (me.allowColors)
- getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithColors);
- else
- getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithoutColors);
- ++lines;
- }
- }
- else
- lines = 1;
-
- draw_fontscale = dfs;
-
- me.realOrigin_y = 0.5 * (1 - lines * me.realFontSize_y);
- }
-
- if(me.isBold)
- draw_endBoldFont();
-
- me.recalcPos = 0;
-}
-void Label_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- SUPER(Label).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
-
- // absSize_y is height of label
- me.realFontSize_y = me.fontSize / absSize_y;
- me.realFontSize_x = me.fontSize / absSize_x;
- if(me.marginLeft)
- me.keepspaceLeft = me.marginLeft * me.realFontSize_x;
- if(me.marginRight)
- me.keepspaceRight = me.marginRight * me.realFontSize_x;
-
- me.recalcPos = 1;
-}
-void Label_configureLabel(entity me, string txt, float sz, float algn)
-{
- me.fontSize = sz;
- me.align = algn;
- me.setText(me, txt);
-}
-void Label_draw(entity me)
-{
- string t;
- vector o;
- if(me.disabled)
- draw_alpha *= me.disabledAlpha;
-
- if(me.textEntity)
- {
- t = me.textEntity.toString(me.textEntity);
- if(t != me.currentText)
- {
- if(me.currentText)
- strunzone(me.currentText);
- me.currentText = strzone(t);
- me.recalcPos = 1;
- }
- }
- else
- t = me.text;
-
- if(me.recalcPos)
- me.recalcPositionWithText(me, t);
-
- if(me.fontSize)
- if(t)
- {
- vector dfs;
- vector fs;
-
- if(me.isBold)
- draw_beginBoldFont();
-
- // set up variables to draw in condensed size, but use hinting for original size
- fs = me.realFontSize;
- fs_x *= me.condenseFactor;
-
- dfs = draw_fontscale;
- draw_fontscale_x *= me.condenseFactor;
-
- if(me.allowCut) // FIXME allowCut incompatible with align != 0
- draw_Text(me.realOrigin, draw_TextShortenToWidth(t, (1 - me.keepspaceLeft - me.keepspaceRight), me.allowColors, fs), fs, me.colorL, me.alpha, me.allowColors);
- else if(me.allowWrap) // FIXME allowWrap incompatible with align != 0
- {
- getWrappedLine_remaining = t;
- o = me.realOrigin;
- while(getWrappedLine_remaining)
- {
- if (me.allowColors)
- t = getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithColors);
- else
- t = getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithoutColors);
- draw_Text(o, t, fs, me.colorL, me.alpha, me.allowColors);
- o_y += me.realFontSize_y;
- }
- }
- else
- draw_Text(me.realOrigin, t, fs, me.colorL, me.alpha, me.allowColors);
-
- draw_fontscale = dfs;
-
- if(me.isBold)
- draw_endBoldFont();
- }
-
- SUPER(Label).draw(me);
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(Label) EXTENDS(Item)
+ METHOD(Label, configureLabel, void(entity, string, float, float))
+ METHOD(Label, draw, void(entity))
+ METHOD(Label, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(Label, setText, void(entity, string))
+ METHOD(Label, toString, string(entity))
+ METHOD(Label, recalcPositionWithText, void(entity, string))
+ ATTRIB(Label, isBold, float, 0)
+ ATTRIB(Label, text, string, string_null)
+ ATTRIB(Label, currentText, string, string_null)
+ ATTRIB(Label, fontSize, float, 8)
+ ATTRIB(Label, align, float, 0.5)
+ ATTRIB(Label, allowCut, float, 0)
+ ATTRIB(Label, allowColors, float, 0)
+ ATTRIB(Label, keepspaceLeft, float, 0) // for use by subclasses (radiobuttons for example)
+ ATTRIB(Label, keepspaceRight, float, 0)
+ ATTRIB(Label, marginLeft, float, 0) // alternate way to specify keepspace* (in characters from the font)
+ ATTRIB(Label, marginRight, float, 0)
+ ATTRIB(Label, realFontSize, vector, '0 0 0')
+ ATTRIB(Label, realOrigin, vector, '0 0 0')
+ ATTRIB(Label, alpha, float, 0.7)
+ ATTRIB(Label, colorL, vector, SKINCOLOR_TEXT)
+ ATTRIB(Label, disabled, float, 0)
+ ATTRIB(Label, disabledAlpha, float, 0.3)
+ ATTRIB(Label, textEntity, entity, NULL)
+ ATTRIB(Label, allowWrap, float, 0)
+ ATTRIB(Label, recalcPos, float, 0)
+ ATTRIB(Label, condenseFactor, float, 1)
+ ATTRIB(Label, overrideRealOrigin, vector, '0 0 0')
+ ATTRIB(Label, overrideCondenseFactor, float, 0)
+ENDCLASS(Label)
+#endif
+
+#ifdef IMPLEMENTATION
+string Label_toString(entity me)
+{
+ return me.text;
+}
+void Label_setText(entity me, string txt)
+{
+ me.text = txt;
+ if(txt != me.currentText)
+ {
+ if(me.currentText)
+ strunzone(me.currentText);
+ me.currentText = strzone(txt);
+ me.recalcPos = 1;
+ }
+}
+void Label_recalcPositionWithText(entity me, string t)
+{
+ float spaceAvail;
+ spaceAvail = 1 - me.keepspaceLeft - me.keepspaceRight;
+
+ if(me.isBold)
+ draw_beginBoldFont();
+
+ float spaceUsed;
+ spaceUsed = draw_TextWidth(t, me.allowColors, me.realFontSize);
+
+ if(spaceUsed <= spaceAvail)
+ {
+ if(!me.overrideRealOrigin_x)
+ me.realOrigin_x = me.align * (spaceAvail - spaceUsed) + me.keepspaceLeft;
+ if(!me.overrideCondenseFactor)
+ me.condenseFactor = 1;
+ }
+ else if(me.allowCut || me.allowWrap)
+ {
+ if(!me.overrideRealOrigin_x)
+ me.realOrigin_x = me.keepspaceLeft;
+ if(!me.overrideCondenseFactor)
+ me.condenseFactor = 1;
+ }
+ else
+ {
+ if(!me.overrideRealOrigin_x)
+ me.realOrigin_x = me.keepspaceLeft;
+ if(!me.overrideCondenseFactor)
+ me.condenseFactor = spaceAvail / spaceUsed;
+ dprintf("NOTE: label text %s too wide for label, condensed by factor %f\n", t, me.condenseFactor);
+ }
+
+ if(!me.overrideRealOrigin_y)
+ {
+ float lines;
+ vector dfs;
+ vector fs;
+
+ // set up variables to draw in condensed size, but use hinting for original size
+ fs = me.realFontSize;
+ fs_x *= me.condenseFactor;
+
+ dfs = draw_fontscale;
+ draw_fontscale_x *= me.condenseFactor;
+
+ if(me.allowCut) // FIXME allowCut incompatible with align != 0
+ lines = 1;
+ else if(me.allowWrap) // FIXME allowWrap incompatible with align != 0
+ {
+ getWrappedLine_remaining = me.text;
+ lines = 0;
+ while(getWrappedLine_remaining)
+ {
+ if (me.allowColors)
+ getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithColors);
+ else
+ getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithoutColors);
+ ++lines;
+ }
+ }
+ else
+ lines = 1;
+
+ draw_fontscale = dfs;
+
+ me.realOrigin_y = 0.5 * (1 - lines * me.realFontSize_y);
+ }
+
+ if(me.isBold)
+ draw_endBoldFont();
+
+ me.recalcPos = 0;
+}
+void Label_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ SUPER(Label).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+
+ // absSize_y is height of label
+ me.realFontSize_y = me.fontSize / absSize_y;
+ me.realFontSize_x = me.fontSize / absSize_x;
+ if(me.marginLeft)
+ me.keepspaceLeft = me.marginLeft * me.realFontSize_x;
+ if(me.marginRight)
+ me.keepspaceRight = me.marginRight * me.realFontSize_x;
+
+ me.recalcPos = 1;
+}
+void Label_configureLabel(entity me, string txt, float sz, float algn)
+{
+ me.fontSize = sz;
+ me.align = algn;
+ me.setText(me, txt);
+}
+void Label_draw(entity me)
+{
+ string t;
+ vector o;
+ if(me.disabled)
+ draw_alpha *= me.disabledAlpha;
+
+ if(me.textEntity)
+ {
+ t = me.textEntity.toString(me.textEntity);
+ if(t != me.currentText)
+ {
+ if(me.currentText)
+ strunzone(me.currentText);
+ me.currentText = strzone(t);
+ me.recalcPos = 1;
+ }
+ }
+ else
+ t = me.text;
+
+ if(me.recalcPos)
+ me.recalcPositionWithText(me, t);
+
+ if(me.fontSize)
+ if(t)
+ {
+ vector dfs;
+ vector fs;
+
+ if(me.isBold)
+ draw_beginBoldFont();
+
+ // set up variables to draw in condensed size, but use hinting for original size
+ fs = me.realFontSize;
+ fs_x *= me.condenseFactor;
+
+ dfs = draw_fontscale;
+ draw_fontscale_x *= me.condenseFactor;
+
+ if(me.allowCut) // FIXME allowCut incompatible with align != 0
+ draw_Text(me.realOrigin, draw_TextShortenToWidth(t, (1 - me.keepspaceLeft - me.keepspaceRight), me.allowColors, fs), fs, me.colorL, me.alpha, me.allowColors);
+ else if(me.allowWrap) // FIXME allowWrap incompatible with align != 0
+ {
+ getWrappedLine_remaining = t;
+ o = me.realOrigin;
+ while(getWrappedLine_remaining)
+ {
+ if (me.allowColors)
+ t = getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithColors);
+ else
+ t = getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithoutColors);
+ draw_Text(o, t, fs, me.colorL, me.alpha, me.allowColors);
+ o_y += me.realFontSize_y;
+ }
+ }
+ else
+ draw_Text(me.realOrigin, t, fs, me.colorL, me.alpha, me.allowColors);
+
+ draw_fontscale = dfs;
+
+ if(me.isBold)
+ draw_endBoldFont();
+ }
+
+ SUPER(Label).draw(me);
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(ListBox) EXTENDS(Item)
- METHOD(ListBox, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(ListBox, configureListBox, void(entity, float, float))
- METHOD(ListBox, draw, void(entity))
- METHOD(ListBox, keyDown, float(entity, float, float, float))
- METHOD(ListBox, mousePress, float(entity, vector))
- METHOD(ListBox, mouseDrag, float(entity, vector))
- METHOD(ListBox, mouseRelease, float(entity, vector))
- METHOD(ListBox, focusLeave, void(entity))
- ATTRIB(ListBox, focusable, float, 1)
- ATTRIB(ListBox, selectedItem, float, 0)
- ATTRIB(ListBox, size, vector, '0 0 0')
- ATTRIB(ListBox, origin, vector, '0 0 0')
- ATTRIB(ListBox, scrollPos, float, 0) // measured in window heights, fixed when needed
- ATTRIB(ListBox, previousValue, float, 0)
- ATTRIB(ListBox, pressed, float, 0) // 0 = normal, 1 = scrollbar dragging, 2 = item dragging, 3 = released
- ATTRIB(ListBox, pressOffset, float, 0)
-
- METHOD(ListBox, updateControlTopBottom, void(entity))
- ATTRIB(ListBox, controlTop, float, 0)
- ATTRIB(ListBox, controlBottom, float, 0)
- ATTRIB(ListBox, controlWidth, float, 0)
- ATTRIB(ListBox, dragScrollTimer, float, 0)
- ATTRIB(ListBox, dragScrollPos, vector, '0 0 0')
-
- ATTRIB(ListBox, src, string, string_null) // scrollbar
- ATTRIB(ListBox, color, vector, '1 1 1')
- ATTRIB(ListBox, color2, vector, '1 1 1')
- ATTRIB(ListBox, colorC, vector, '1 1 1')
- ATTRIB(ListBox, colorF, vector, '1 1 1')
- ATTRIB(ListBox, tolerance, vector, '0 0 0') // drag tolerance
- ATTRIB(ListBox, scrollbarWidth, float, 0) // pixels
- ATTRIB(ListBox, nItems, float, 42)
- ATTRIB(ListBox, itemHeight, float, 0)
- ATTRIB(ListBox, colorBG, vector, '0 0 0')
- ATTRIB(ListBox, alphaBG, float, 0)
-
- ATTRIB(ListBox, lastClickedItem, float, -1)
- ATTRIB(ListBox, lastClickedTime, float, 0)
-
- METHOD(ListBox, drawListBoxItem, void(entity, float, vector, float)) // item number, width/height, selected
- METHOD(ListBox, clickListBoxItem, void(entity, float, vector)) // item number, relative clickpos
- METHOD(ListBox, doubleClickListBoxItem, void(entity, float, vector)) // item number, relative clickpos
- METHOD(ListBox, setSelected, void(entity, float))
-
- METHOD(ListBox, getLastFullyVisibleItemAtScrollPos, float(entity, float))
- METHOD(ListBox, getFirstFullyVisibleItemAtScrollPos, float(entity, float))
-
- // NOTE: override these four methods if you want variable sized list items
- METHOD(ListBox, getTotalHeight, float(entity))
- METHOD(ListBox, getItemAtPos, float(entity, float))
- METHOD(ListBox, getItemStart, float(entity, float))
- METHOD(ListBox, getItemHeight, float(entity, float))
- // NOTE: if getItemAt* are overridden, it may make sense to cache the
- // start and height of the last item returned by getItemAtPos and fast
- // track returning their properties for getItemStart and getItemHeight.
- // The "hot" code path calls getItemAtPos first, then will query
- // getItemStart and getItemHeight on it soon.
- // When overriding, the following consistency rules must hold:
- // getTotalHeight() == SUM(getItemHeight(i), i, 0, me.nItems-1)
- // getItemStart(i+1) == getItemStart(i) + getItemHeight(i)
- // for 0 <= i < me.nItems-1
- // getItemStart(0) == 0
- // getItemStart(getItemAtPos(p)) <= p
- // if p >= 0
- // getItemAtPos(p) == 0
- // if p < 0
- // getItemStart(getItemAtPos(p)) + getItemHeight(getItemAtPos(p)) > p
- // if p < getTotalHeigt()
- // getItemAtPos(p) == me.nItems - 1
- // if p >= getTotalHeight()
-ENDCLASS(ListBox)
-#endif
-
-#ifdef IMPLEMENTATION
-void ListBox_setSelected(entity me, float i)
-{
- me.selectedItem = bound(0, i, me.nItems - 1);
-}
-void ListBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- SUPER(ListBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
- me.controlWidth = me.scrollbarWidth / absSize_x;
-}
-void ListBox_configureListBox(entity me, float theScrollbarWidth, float theItemHeight)
-{
- me.scrollbarWidth = theScrollbarWidth;
- me.itemHeight = theItemHeight;
-}
-
-float ListBox_getTotalHeight(entity me)
-{
- return me.nItems * me.itemHeight;
-}
-float ListBox_getItemAtPos(entity me, float pos)
-{
- return floor(pos / me.itemHeight);
-}
-float ListBox_getItemStart(entity me, float i)
-{
- return me.itemHeight * i;
-}
-float ListBox_getItemHeight(entity me, float i)
-{
- return me.itemHeight;
-}
-
-float ListBox_getLastFullyVisibleItemAtScrollPos(entity me, float pos)
-{
- return me.getItemAtPos(me, pos + 1.001) - 1;
-}
-float ListBox_getFirstFullyVisibleItemAtScrollPos(entity me, float pos)
-{
- return me.getItemAtPos(me, pos - 0.001) + 1;
-}
-float ListBox_keyDown(entity me, float key, float ascii, float shift)
-{
- me.dragScrollTimer = time;
- if(key == K_MWHEELUP)
- {
- me.scrollPos = max(me.scrollPos - 0.5, 0);
- me.setSelected(me, min(me.selectedItem, me.getLastFullyVisibleItemAtScrollPos(me, me.scrollPos)));
- }
- else if(key == K_MWHEELDOWN)
- {
- me.scrollPos = min(me.scrollPos + 0.5, me.getTotalHeight(me) - 1);
- me.setSelected(me, max(me.selectedItem, me.getFirstFullyVisibleItemAtScrollPos(me, me.scrollPos)));
- }
- else if(key == K_PGUP || key == K_KP_PGUP)
- {
- float i = me.selectedItem;
- float a = me.getItemHeight(me, i);
- for(;;)
- {
- --i;
- if (i < 0)
- break;
- a += me.getItemHeight(me, i);
- if (a >= 1)
- break;
- }
- me.setSelected(me, i + 1);
- }
- else if(key == K_PGDN || key == K_KP_PGDN)
- {
- float i = me.selectedItem;
- float a = me.getItemHeight(me, i);
- for(;;)
- {
- ++i;
- if (i >= me.nItems)
- break;
- a += me.getItemHeight(me, i);
- if (a >= 1)
- break;
- }
- me.setSelected(me, i - 1);
- }
- else if(key == K_UPARROW || key == K_KP_UPARROW)
- me.setSelected(me, me.selectedItem - 1);
- else if(key == K_DOWNARROW || key == K_KP_DOWNARROW)
- me.setSelected(me, me.selectedItem + 1);
- else if(key == K_HOME || key == K_KP_HOME)
- {
- me.scrollPos = 0;
- me.setSelected(me, 0);
- }
- else if(key == K_END || key == K_KP_END)
- {
- me.scrollPos = max(0, me.getTotalHeight(me) - 1);
- me.setSelected(me, me.nItems - 1);
- }
- else
- return 0;
- return 1;
-}
-float ListBox_mouseDrag(entity me, vector pos)
-{
- float hit;
- float i;
- me.updateControlTopBottom(me);
- me.dragScrollPos = pos;
- if(me.pressed == 1)
- {
- hit = 1;
- if(pos_x < 1 - me.controlWidth - me.tolerance_y * me.controlWidth) hit = 0;
- if(pos_y < 0 - me.tolerance_x) hit = 0;
- if(pos_x >= 1 + me.tolerance_y * me.controlWidth) hit = 0;
- if(pos_y >= 1 + me.tolerance_x) hit = 0;
- if(hit)
- {
- // calculate new pos to v
- float d;
- d = (pos_y - me.pressOffset) / (1 - (me.controlBottom - me.controlTop)) * (me.getTotalHeight(me) - 1);
- me.scrollPos = me.previousValue + d;
- }
- else
- me.scrollPos = me.previousValue;
- me.scrollPos = min(me.scrollPos, me.getTotalHeight(me) - 1);
- me.scrollPos = max(me.scrollPos, 0);
- i = min(me.selectedItem, me.getLastFullyVisibleItemAtScrollPos(me, me.scrollPos));
- i = max(i, ListBox_getFirstFullyVisibleItemAtScrollPos(me, me.scrollPos));
- me.setSelected(me, i);
- }
- else if(me.pressed == 2)
- {
- me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos_y));
- }
- return 1;
-}
-float ListBox_mousePress(entity me, vector pos)
-{
- if(pos_x < 0) return 0;
- if(pos_y < 0) return 0;
- if(pos_x >= 1) return 0;
- if(pos_y >= 1) return 0;
- me.dragScrollPos = pos;
- me.updateControlTopBottom(me);
- me.dragScrollTimer = time;
- if(pos_x >= 1 - me.controlWidth)
- {
- // if hit, set me.pressed, otherwise scroll by one page
- if(pos_y < me.controlTop)
- {
- // page up
- me.scrollPos = max(me.scrollPos - 1, 0);
- me.setSelected(me, min(me.selectedItem, ListBox_getLastFullyVisibleItemAtScrollPos(me, me.scrollPos)));
- }
- else if(pos_y > me.controlBottom)
- {
- // page down
- me.scrollPos = min(me.scrollPos + 1, me.getTotalHeight(me) - 1);
- me.setSelected(me, max(me.selectedItem, ListBox_getFirstFullyVisibleItemAtScrollPos(me, me.scrollPos)));
- }
- else
- {
- me.pressed = 1;
- me.pressOffset = pos_y;
- me.previousValue = me.scrollPos;
- }
- }
- else
- {
- // continue doing that while dragging (even when dragging outside). When releasing, forward the click to the then selected item.
- me.pressed = 2;
- // an item has been clicked. Select it, ...
- me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos_y));
- }
- return 1;
-}
-float ListBox_mouseRelease(entity me, vector pos)
-{
- if(me.pressed == 1)
- {
- // slider dragging mode
- // in that case, nothing happens on releasing
- }
- else if(me.pressed == 2)
- {
- me.pressed = 3; // do that here, so setSelected can know the mouse has been released
- // item dragging mode
- // select current one one last time...
- me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos_y));
- // and give it a nice click event
- if(me.nItems > 0)
- {
- vector where = globalToBox(pos, eY * (me.getItemStart(me, me.selectedItem) - me.scrollPos), eX * (1 - me.controlWidth) + eY * me.getItemHeight(me, me.selectedItem));
-
- if((me.selectedItem == me.lastClickedItem) && (time < me.lastClickedTime + 0.3))
- me.doubleClickListBoxItem(me, me.selectedItem, where);
- else
- me.clickListBoxItem(me, me.selectedItem, where);
-
- me.lastClickedItem = me.selectedItem;
- me.lastClickedTime = time;
- }
- }
- me.pressed = 0;
- return 1;
-}
-void ListBox_focusLeave(entity me)
-{
- // Reset the var pressed in case listbox loses focus
- // by a mouse click on an item of the list
- // for example showing a dialog on right click
- me.pressed = 0;
-}
-void ListBox_updateControlTopBottom(entity me)
-{
- float f;
- // scrollPos is in 0..1 and indicates where the "page" currently shown starts.
- if(me.getTotalHeight(me) <= 1)
- {
- // we don't need no stinkin' scrollbar, we don't need no view control...
- me.controlTop = 0;
- me.controlBottom = 1;
- me.scrollPos = 0;
- }
- else
- {
- if(frametime) // only do this in draw frames
- {
- if(me.dragScrollTimer < time)
- {
- float save;
- save = me.scrollPos;
- // if selected item is below listbox, increase scrollpos so it is in
- me.scrollPos = max(me.scrollPos, me.getItemStart(me, me.selectedItem) + me.getItemHeight(me, me.selectedItem) - 1);
- // if selected item is above listbox, decrease scrollpos so it is in
- me.scrollPos = min(me.scrollPos, me.getItemStart(me, me.selectedItem));
- if(me.scrollPos != save)
- me.dragScrollTimer = time + 0.2;
- }
- }
- // if scroll pos is below end of list, fix it
- me.scrollPos = min(me.scrollPos, me.getTotalHeight(me) - 1);
- // if scroll pos is above beginning of list, fix it
- me.scrollPos = max(me.scrollPos, 0);
- // now that we know where the list is scrolled to, find out where to draw the control
- me.controlTop = max(0, me.scrollPos / me.getTotalHeight(me));
- me.controlBottom = min((me.scrollPos + 1) / me.getTotalHeight(me), 1);
-
- float minfactor;
- minfactor = 2 * me.controlWidth / me.size_y * me.size_x;
- f = me.controlBottom - me.controlTop;
- if(f < minfactor) // FIXME good default?
- {
- // f * X + 1 * (1-X) = minfactor
- // (f - 1) * X + 1 = minfactor
- // (f - 1) * X = minfactor - 1
- // X = (minfactor - 1) / (f - 1)
- f = (minfactor - 1) / (f - 1);
- me.controlTop = me.controlTop * f + 0 * (1 - f);
- me.controlBottom = me.controlBottom * f + 1 * (1 - f);
- }
- }
-}
-void ListBox_draw(entity me)
-{
- float i;
- vector absSize, fillSize = '0 0 0';
- vector oldshift, oldscale;
- if(me.pressed == 2)
- me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event
- me.updateControlTopBottom(me);
- fillSize_x = (1 - me.controlWidth);
- if(me.alphaBG)
- draw_Fill('0 0 0', '0 1 0' + fillSize, me.colorBG, me.alphaBG);
- if(me.controlWidth)
- {
- draw_VertButtonPicture(eX * (1 - me.controlWidth), strcat(me.src, "_s"), eX * me.controlWidth + eY, me.color2, 1);
- if(me.getTotalHeight(me) > 1)
- {
- vector o, s;
- o = eX * (1 - me.controlWidth) + eY * me.controlTop;
- s = eX * me.controlWidth + eY * (me.controlBottom - me.controlTop);
- if(me.pressed == 1)
- draw_VertButtonPicture(o, strcat(me.src, "_c"), s, me.colorC, 1);
- else if(me.focused)
- draw_VertButtonPicture(o, strcat(me.src, "_f"), s, me.colorF, 1);
- else
- draw_VertButtonPicture(o, strcat(me.src, "_n"), s, me.color, 1);
- }
- }
- draw_SetClip();
- oldshift = draw_shift;
- oldscale = draw_scale;
- float y;
- i = me.getItemAtPos(me, me.scrollPos);
- y = me.getItemStart(me, i) - me.scrollPos;
- for(; i < me.nItems && y < 1; ++i)
- {
- draw_shift = boxToGlobal(eY * y, oldshift, oldscale);
- vector relSize = eX * (1 - me.controlWidth) + eY * me.getItemHeight(me, i);
- absSize = boxToGlobalSize(relSize, me.size);
- draw_scale = boxToGlobalSize(relSize, oldscale);
- me.drawListBoxItem(me, i, absSize, (me.selectedItem == i));
- y += relSize_y;
- }
- draw_ClearClip();
-
- draw_shift = oldshift;
- draw_scale = oldscale;
- SUPER(ListBox).draw(me);
-}
-
-void ListBox_clickListBoxItem(entity me, float i, vector where)
-{
- // template method
-}
-
-void ListBox_doubleClickListBoxItem(entity me, float i, vector where)
-{
- // template method
-}
-
-void ListBox_drawListBoxItem(entity me, float i, vector absSize, float selected)
-{
- draw_Text('0 0 0', sprintf(_("Item %d"), i), eX * (8 / absSize_x) + eY * (8 / absSize_y), (selected ? '0 1 0' : '1 1 1'), 1, 0);
-}
-#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(ListBox) EXTENDS(Item)
+ METHOD(ListBox, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(ListBox, configureListBox, void(entity, float, float))
+ METHOD(ListBox, draw, void(entity))
+ METHOD(ListBox, keyDown, float(entity, float, float, float))
+ METHOD(ListBox, mousePress, float(entity, vector))
+ METHOD(ListBox, mouseDrag, float(entity, vector))
+ METHOD(ListBox, mouseRelease, float(entity, vector))
+ METHOD(ListBox, focusLeave, void(entity))
+ ATTRIB(ListBox, focusable, float, 1)
+ ATTRIB(ListBox, selectedItem, float, 0)
+ ATTRIB(ListBox, size, vector, '0 0 0')
+ ATTRIB(ListBox, origin, vector, '0 0 0')
+ ATTRIB(ListBox, scrollPos, float, 0) // measured in window heights, fixed when needed
+ ATTRIB(ListBox, previousValue, float, 0)
+ ATTRIB(ListBox, pressed, float, 0) // 0 = normal, 1 = scrollbar dragging, 2 = item dragging, 3 = released
+ ATTRIB(ListBox, pressOffset, float, 0)
+
+ METHOD(ListBox, updateControlTopBottom, void(entity))
+ ATTRIB(ListBox, controlTop, float, 0)
+ ATTRIB(ListBox, controlBottom, float, 0)
+ ATTRIB(ListBox, controlWidth, float, 0)
+ ATTRIB(ListBox, dragScrollTimer, float, 0)
+ ATTRIB(ListBox, dragScrollPos, vector, '0 0 0')
+
+ ATTRIB(ListBox, src, string, string_null) // scrollbar
+ ATTRIB(ListBox, color, vector, '1 1 1')
+ ATTRIB(ListBox, color2, vector, '1 1 1')
+ ATTRIB(ListBox, colorC, vector, '1 1 1')
+ ATTRIB(ListBox, colorF, vector, '1 1 1')
+ ATTRIB(ListBox, tolerance, vector, '0 0 0') // drag tolerance
+ ATTRIB(ListBox, scrollbarWidth, float, 0) // pixels
+ ATTRIB(ListBox, nItems, float, 42)
+ ATTRIB(ListBox, itemHeight, float, 0)
+ ATTRIB(ListBox, colorBG, vector, '0 0 0')
+ ATTRIB(ListBox, alphaBG, float, 0)
+
+ ATTRIB(ListBox, lastClickedItem, float, -1)
+ ATTRIB(ListBox, lastClickedTime, float, 0)
+
+ METHOD(ListBox, drawListBoxItem, void(entity, float, vector, float)) // item number, width/height, selected
+ METHOD(ListBox, clickListBoxItem, void(entity, float, vector)) // item number, relative clickpos
+ METHOD(ListBox, doubleClickListBoxItem, void(entity, float, vector)) // item number, relative clickpos
+ METHOD(ListBox, setSelected, void(entity, float))
+
+ METHOD(ListBox, getLastFullyVisibleItemAtScrollPos, float(entity, float))
+ METHOD(ListBox, getFirstFullyVisibleItemAtScrollPos, float(entity, float))
+
+ // NOTE: override these four methods if you want variable sized list items
+ METHOD(ListBox, getTotalHeight, float(entity))
+ METHOD(ListBox, getItemAtPos, float(entity, float))
+ METHOD(ListBox, getItemStart, float(entity, float))
+ METHOD(ListBox, getItemHeight, float(entity, float))
+ // NOTE: if getItemAt* are overridden, it may make sense to cache the
+ // start and height of the last item returned by getItemAtPos and fast
+ // track returning their properties for getItemStart and getItemHeight.
+ // The "hot" code path calls getItemAtPos first, then will query
+ // getItemStart and getItemHeight on it soon.
+ // When overriding, the following consistency rules must hold:
+ // getTotalHeight() == SUM(getItemHeight(i), i, 0, me.nItems-1)
+ // getItemStart(i+1) == getItemStart(i) + getItemHeight(i)
+ // for 0 <= i < me.nItems-1
+ // getItemStart(0) == 0
+ // getItemStart(getItemAtPos(p)) <= p
+ // if p >= 0
+ // getItemAtPos(p) == 0
+ // if p < 0
+ // getItemStart(getItemAtPos(p)) + getItemHeight(getItemAtPos(p)) > p
+ // if p < getTotalHeigt()
+ // getItemAtPos(p) == me.nItems - 1
+ // if p >= getTotalHeight()
+ENDCLASS(ListBox)
+#endif
+
+#ifdef IMPLEMENTATION
+void ListBox_setSelected(entity me, float i)
+{
+ me.selectedItem = bound(0, i, me.nItems - 1);
+}
+void ListBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ SUPER(ListBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+ me.controlWidth = me.scrollbarWidth / absSize_x;
+}
+void ListBox_configureListBox(entity me, float theScrollbarWidth, float theItemHeight)
+{
+ me.scrollbarWidth = theScrollbarWidth;
+ me.itemHeight = theItemHeight;
+}
+
+float ListBox_getTotalHeight(entity me)
+{
+ return me.nItems * me.itemHeight;
+}
+float ListBox_getItemAtPos(entity me, float pos)
+{
+ return floor(pos / me.itemHeight);
+}
+float ListBox_getItemStart(entity me, float i)
+{
+ return me.itemHeight * i;
+}
+float ListBox_getItemHeight(entity me, float i)
+{
+ return me.itemHeight;
+}
+
+float ListBox_getLastFullyVisibleItemAtScrollPos(entity me, float pos)
+{
+ return me.getItemAtPos(me, pos + 1.001) - 1;
+}
+float ListBox_getFirstFullyVisibleItemAtScrollPos(entity me, float pos)
+{
+ return me.getItemAtPos(me, pos - 0.001) + 1;
+}
+float ListBox_keyDown(entity me, float key, float ascii, float shift)
+{
+ me.dragScrollTimer = time;
+ if(key == K_MWHEELUP)
+ {
+ me.scrollPos = max(me.scrollPos - 0.5, 0);
+ me.setSelected(me, min(me.selectedItem, me.getLastFullyVisibleItemAtScrollPos(me, me.scrollPos)));
+ }
+ else if(key == K_MWHEELDOWN)
+ {
+ me.scrollPos = min(me.scrollPos + 0.5, me.getTotalHeight(me) - 1);
+ me.setSelected(me, max(me.selectedItem, me.getFirstFullyVisibleItemAtScrollPos(me, me.scrollPos)));
+ }
+ else if(key == K_PGUP || key == K_KP_PGUP)
+ {
+ float i = me.selectedItem;
+ float a = me.getItemHeight(me, i);
+ for(;;)
+ {
+ --i;
+ if (i < 0)
+ break;
+ a += me.getItemHeight(me, i);
+ if (a >= 1)
+ break;
+ }
+ me.setSelected(me, i + 1);
+ }
+ else if(key == K_PGDN || key == K_KP_PGDN)
+ {
+ float i = me.selectedItem;
+ float a = me.getItemHeight(me, i);
+ for(;;)
+ {
+ ++i;
+ if (i >= me.nItems)
+ break;
+ a += me.getItemHeight(me, i);
+ if (a >= 1)
+ break;
+ }
+ me.setSelected(me, i - 1);
+ }
+ else if(key == K_UPARROW || key == K_KP_UPARROW)
+ me.setSelected(me, me.selectedItem - 1);
+ else if(key == K_DOWNARROW || key == K_KP_DOWNARROW)
+ me.setSelected(me, me.selectedItem + 1);
+ else if(key == K_HOME || key == K_KP_HOME)
+ {
+ me.scrollPos = 0;
+ me.setSelected(me, 0);
+ }
+ else if(key == K_END || key == K_KP_END)
+ {
+ me.scrollPos = max(0, me.getTotalHeight(me) - 1);
+ me.setSelected(me, me.nItems - 1);
+ }
+ else
+ return 0;
+ return 1;
+}
+float ListBox_mouseDrag(entity me, vector pos)
+{
+ float hit;
+ float i;
+ me.updateControlTopBottom(me);
+ me.dragScrollPos = pos;
+ if(me.pressed == 1)
+ {
+ hit = 1;
+ if(pos_x < 1 - me.controlWidth - me.tolerance_y * me.controlWidth) hit = 0;
+ if(pos_y < 0 - me.tolerance_x) hit = 0;
+ if(pos_x >= 1 + me.tolerance_y * me.controlWidth) hit = 0;
+ if(pos_y >= 1 + me.tolerance_x) hit = 0;
+ if(hit)
+ {
+ // calculate new pos to v
+ float d;
+ d = (pos_y - me.pressOffset) / (1 - (me.controlBottom - me.controlTop)) * (me.getTotalHeight(me) - 1);
+ me.scrollPos = me.previousValue + d;
+ }
+ else
+ me.scrollPos = me.previousValue;
+ me.scrollPos = min(me.scrollPos, me.getTotalHeight(me) - 1);
+ me.scrollPos = max(me.scrollPos, 0);
+ i = min(me.selectedItem, me.getLastFullyVisibleItemAtScrollPos(me, me.scrollPos));
+ i = max(i, ListBox_getFirstFullyVisibleItemAtScrollPos(me, me.scrollPos));
+ me.setSelected(me, i);
+ }
+ else if(me.pressed == 2)
+ {
+ me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos_y));
+ }
+ return 1;
+}
+float ListBox_mousePress(entity me, vector pos)
+{
+ if(pos_x < 0) return 0;
+ if(pos_y < 0) return 0;
+ if(pos_x >= 1) return 0;
+ if(pos_y >= 1) return 0;
+ me.dragScrollPos = pos;
+ me.updateControlTopBottom(me);
+ me.dragScrollTimer = time;
+ if(pos_x >= 1 - me.controlWidth)
+ {
+ // if hit, set me.pressed, otherwise scroll by one page
+ if(pos_y < me.controlTop)
+ {
+ // page up
+ me.scrollPos = max(me.scrollPos - 1, 0);
+ me.setSelected(me, min(me.selectedItem, ListBox_getLastFullyVisibleItemAtScrollPos(me, me.scrollPos)));
+ }
+ else if(pos_y > me.controlBottom)
+ {
+ // page down
+ me.scrollPos = min(me.scrollPos + 1, me.getTotalHeight(me) - 1);
+ me.setSelected(me, max(me.selectedItem, ListBox_getFirstFullyVisibleItemAtScrollPos(me, me.scrollPos)));
+ }
+ else
+ {
+ me.pressed = 1;
+ me.pressOffset = pos_y;
+ me.previousValue = me.scrollPos;
+ }
+ }
+ else
+ {
+ // continue doing that while dragging (even when dragging outside). When releasing, forward the click to the then selected item.
+ me.pressed = 2;
+ // an item has been clicked. Select it, ...
+ me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos_y));
+ }
+ return 1;
+}
+float ListBox_mouseRelease(entity me, vector pos)
+{
+ if(me.pressed == 1)
+ {
+ // slider dragging mode
+ // in that case, nothing happens on releasing
+ }
+ else if(me.pressed == 2)
+ {
+ me.pressed = 3; // do that here, so setSelected can know the mouse has been released
+ // item dragging mode
+ // select current one one last time...
+ me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos_y));
+ // and give it a nice click event
+ if(me.nItems > 0)
+ {
+ vector where = globalToBox(pos, eY * (me.getItemStart(me, me.selectedItem) - me.scrollPos), eX * (1 - me.controlWidth) + eY * me.getItemHeight(me, me.selectedItem));
+
+ if((me.selectedItem == me.lastClickedItem) && (time < me.lastClickedTime + 0.3))
+ me.doubleClickListBoxItem(me, me.selectedItem, where);
+ else
+ me.clickListBoxItem(me, me.selectedItem, where);
+
+ me.lastClickedItem = me.selectedItem;
+ me.lastClickedTime = time;
+ }
+ }
+ me.pressed = 0;
+ return 1;
+}
+void ListBox_focusLeave(entity me)
+{
+ // Reset the var pressed in case listbox loses focus
+ // by a mouse click on an item of the list
+ // for example showing a dialog on right click
+ me.pressed = 0;
+}
+void ListBox_updateControlTopBottom(entity me)
+{
+ float f;
+ // scrollPos is in 0..1 and indicates where the "page" currently shown starts.
+ if(me.getTotalHeight(me) <= 1)
+ {
+ // we don't need no stinkin' scrollbar, we don't need no view control...
+ me.controlTop = 0;
+ me.controlBottom = 1;
+ me.scrollPos = 0;
+ }
+ else
+ {
+ if(frametime) // only do this in draw frames
+ {
+ if(me.dragScrollTimer < time)
+ {
+ float save;
+ save = me.scrollPos;
+ // if selected item is below listbox, increase scrollpos so it is in
+ me.scrollPos = max(me.scrollPos, me.getItemStart(me, me.selectedItem) + me.getItemHeight(me, me.selectedItem) - 1);
+ // if selected item is above listbox, decrease scrollpos so it is in
+ me.scrollPos = min(me.scrollPos, me.getItemStart(me, me.selectedItem));
+ if(me.scrollPos != save)
+ me.dragScrollTimer = time + 0.2;
+ }
+ }
+ // if scroll pos is below end of list, fix it
+ me.scrollPos = min(me.scrollPos, me.getTotalHeight(me) - 1);
+ // if scroll pos is above beginning of list, fix it
+ me.scrollPos = max(me.scrollPos, 0);
+ // now that we know where the list is scrolled to, find out where to draw the control
+ me.controlTop = max(0, me.scrollPos / me.getTotalHeight(me));
+ me.controlBottom = min((me.scrollPos + 1) / me.getTotalHeight(me), 1);
+
+ float minfactor;
+ minfactor = 2 * me.controlWidth / me.size_y * me.size_x;
+ f = me.controlBottom - me.controlTop;
+ if(f < minfactor) // FIXME good default?
+ {
+ // f * X + 1 * (1-X) = minfactor
+ // (f - 1) * X + 1 = minfactor
+ // (f - 1) * X = minfactor - 1
+ // X = (minfactor - 1) / (f - 1)
+ f = (minfactor - 1) / (f - 1);
+ me.controlTop = me.controlTop * f + 0 * (1 - f);
+ me.controlBottom = me.controlBottom * f + 1 * (1 - f);
+ }
+ }
+}
+void ListBox_draw(entity me)
+{
+ float i;
+ vector absSize, fillSize = '0 0 0';
+ vector oldshift, oldscale;
+ if(me.pressed == 2)
+ me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event
+ me.updateControlTopBottom(me);
+ fillSize_x = (1 - me.controlWidth);
+ if(me.alphaBG)
+ draw_Fill('0 0 0', '0 1 0' + fillSize, me.colorBG, me.alphaBG);
+ if(me.controlWidth)
+ {
+ draw_VertButtonPicture(eX * (1 - me.controlWidth), strcat(me.src, "_s"), eX * me.controlWidth + eY, me.color2, 1);
+ if(me.getTotalHeight(me) > 1)
+ {
+ vector o, s;
+ o = eX * (1 - me.controlWidth) + eY * me.controlTop;
+ s = eX * me.controlWidth + eY * (me.controlBottom - me.controlTop);
+ if(me.pressed == 1)
+ draw_VertButtonPicture(o, strcat(me.src, "_c"), s, me.colorC, 1);
+ else if(me.focused)
+ draw_VertButtonPicture(o, strcat(me.src, "_f"), s, me.colorF, 1);
+ else
+ draw_VertButtonPicture(o, strcat(me.src, "_n"), s, me.color, 1);
+ }
+ }
+ draw_SetClip();
+ oldshift = draw_shift;
+ oldscale = draw_scale;
+ float y;
+ i = me.getItemAtPos(me, me.scrollPos);
+ y = me.getItemStart(me, i) - me.scrollPos;
+ for(; i < me.nItems && y < 1; ++i)
+ {
+ draw_shift = boxToGlobal(eY * y, oldshift, oldscale);
+ vector relSize = eX * (1 - me.controlWidth) + eY * me.getItemHeight(me, i);
+ absSize = boxToGlobalSize(relSize, me.size);
+ draw_scale = boxToGlobalSize(relSize, oldscale);
+ me.drawListBoxItem(me, i, absSize, (me.selectedItem == i));
+ y += relSize_y;
+ }
+ draw_ClearClip();
+
+ draw_shift = oldshift;
+ draw_scale = oldscale;
+ SUPER(ListBox).draw(me);
+}
+
+void ListBox_clickListBoxItem(entity me, float i, vector where)
+{
+ // template method
+}
+
+void ListBox_doubleClickListBoxItem(entity me, float i, vector where)
+{
+ // template method
+}
+
+void ListBox_drawListBoxItem(entity me, float i, vector absSize, float selected)
+{
+ draw_Text('0 0 0', sprintf(_("Item %d"), i), eX * (8 / absSize_x) + eY * (8 / absSize_y), (selected ? '0 1 0' : '1 1 1'), 1, 0);
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(ModalController) EXTENDS(Container)
- METHOD(ModalController, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(ModalController, draw, void(entity))
- METHOD(ModalController, showChild, void(entity, entity, vector, vector, float))
- METHOD(ModalController, hideChild, void(entity, entity, float))
- METHOD(ModalController, hideAll, void(entity, float))
- METHOD(ModalController, addItem, void(entity, entity, vector, vector, float))
- METHOD(ModalController, addTab, void(entity, entity, entity))
-
- METHOD(ModalController, initializeDialog, void(entity, entity))
-
- METHOD(ModalController, switchState, void(entity, entity, float, float))
- ATTRIB(ModalController, origin, vector, '0 0 0')
- ATTRIB(ModalController, size, vector, '0 0 0')
- ATTRIB(ModalController, previousButton, entity, NULL)
- ATTRIB(ModalController, fadedAlpha, float, 0.3)
-ENDCLASS(ModalController)
-
-.entity tabSelectingButton;
-.vector origin;
-.vector size;
-void TabButton_Click(entity button, entity tab); // assumes a button has set the above fields to its own absolute origin, its size, and the tab to activate
-void DialogOpenButton_Click(entity button, entity tab); // assumes a button has set the above fields to its own absolute origin, its size, and the tab to activate
-void DialogOpenButton_Click_withCoords(entity button, entity tab, vector theOrigin, vector theSize);
-void DialogCloseButton_Click(entity button, entity tab); // assumes a button has set the above fields to the tab to close
-#endif
-
-#ifdef IMPLEMENTATION
-
-// modal dialog controller
-// handles a stack of dialog elements
-// each element can have one of the following states:
-// 0: hidden (fading out)
-// 1: visible (zooming in)
-// 2: greyed out (inactive)
-// While an animation is running, no item has focus. When an animation is done,
-// the topmost item gets focus.
-// The items are assumed to be added in overlapping order, that is, the lowest
-// window must get added first.
-//
-// Possible uses:
-// - to control a modal dialog:
-// - show modal dialog: me.showChild(me, childItem, buttonAbsOrigin, buttonAbsSize, 0) // childItem also gets focus
-// - dismiss modal dialog: me.hideChild(me, childItem, 0) // childItem fades out and relinquishes focus
-// - show first screen in m_show: me.hideAll(me, 1); me.showChild(me, me.firstChild, '0 0 0', '0 0 0', 1);
-// - to show a temporary dialog instead of the menu (teamselect): me.hideAll(me, 1); me.showChild(me, teamSelectDialog, '0 0 0', '0 0 0', 1);
-// - as a tabbed dialog control:
-// - to initialize: me.hideAll(me, 1); me.showChild(me, me.firstChild, '0 0 0', '0 0 0', 1);
-// - to show a tab: me.hideChild(me, currentTab, 0); me.showChild(me, newTab, buttonAbsOrigin, buttonAbsSize, 0);
-
-.vector ModalController_initialSize;
-.vector ModalController_initialOrigin;
-.vector ModalController_initialFontScale;
-.float ModalController_initialAlpha;
-.vector ModalController_buttonSize;
-.vector ModalController_buttonOrigin;
-.float ModalController_state;
-.float ModalController_factor;
-.entity ModalController_controllingButton;
-
-void ModalController_initializeDialog(entity me, entity root)
-{
- me.hideAll(me, 1);
- me.showChild(me, root, '0 0 0', '0 0 0', 1); // someone else animates for us
-}
-
-void TabButton_Click(entity button, entity tab)
-{
- if(tab.ModalController_state == 1)
- return;
- tab.parent.hideAll(tab.parent, 0);
- button.forcePressed = 1;
- tab.ModalController_controllingButton = button;
- tab.parent.showChild(tab.parent, tab, button.origin, button.size, 0);
-}
-
-void DialogOpenButton_Click(entity button, entity tab)
-{
- DialogOpenButton_Click_withCoords(button, tab, button.origin, button.size);
-}
-
-void DialogOpenButton_Click_withCoords(entity button, entity tab, vector theOrigin, vector theSize)
-{
- if(tab.ModalController_state)
- return;
- if(button)
- button.forcePressed = 1;
- if(tab.parent.focusedChild)
- tab.parent.focusedChild.saveFocus(tab.parent.focusedChild);
- tab.ModalController_controllingButton = button;
- tab.parent.showChild(tab.parent, tab, theOrigin, theSize, 0);
-}
-
-void DialogCloseButton_Click(entity button, entity tab)
-{
- tab.parent.hideChild(tab.parent, tab, 0);
-}
-
-void ModalController_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- me.resizeNotifyLie(me, relOrigin, relSize, absOrigin, absSize, ModalController_initialOrigin, ModalController_initialSize, ModalController_initialFontScale);
-}
-
-void ModalController_switchState(entity me, entity other, float state, float skipAnimation)
-{
- float previousState;
- previousState = other.ModalController_state;
- if(state == previousState && !skipAnimation)
- return;
- other.ModalController_state = state;
- switch(state)
- {
- case 0:
- other.ModalController_factor = 1 - other.Container_alpha / other.ModalController_initialAlpha;
- // fading out
- break;
- case 1:
- other.ModalController_factor = other.Container_alpha / other.ModalController_initialAlpha;
- if(previousState == 0 && !skipAnimation)
- {
- other.Container_origin = other.ModalController_buttonOrigin;
- other.Container_size = other.ModalController_buttonSize;
- }
- // zooming in
- break;
- case 2:
- other.ModalController_factor = bound(0, (1 - other.Container_alpha / other.ModalController_initialAlpha) / me.fadedAlpha, 1);
- // fading out halfway
- break;
- }
- if(skipAnimation)
- other.ModalController_factor = 1;
-}
-
-void ModalController_draw(entity me)
-{
- entity e;
- entity front;
- float animating;
- float f; // animation factor
- float df; // animation step size
- float prevFactor, targetFactor;
- vector targetOrigin, targetSize; float targetAlpha;
- vector fs;
- animating = 0;
-
- front = world;
- for(e = me.firstChild; e; e = e.nextSibling)
- if(e.ModalController_state)
- {
- if(front)
- me.switchState(me, front, 2, 0);
- front = e;
- }
- if(front)
- me.switchState(me, front, 1, 0);
-
- df = frametime * 3; // animation speed
-
- for(e = me.firstChild; e; e = e.nextSibling)
- {
- f = (e.ModalController_factor = min(1, e.ModalController_factor + df));
- if(e.ModalController_state)
- if(f < 1)
- animating = 1;
-
- if(f < 1)
- {
- prevFactor = (1 - f) / (1 - f + df);
- targetFactor = df / (1 - f + df);
- }
- else
- {
- prevFactor = 0;
- targetFactor = 1;
- }
-
- if(e.ModalController_state == 2)
- {
- // fading out partially
- targetOrigin = e.Container_origin; // stay as is
- targetSize = e.Container_size; // stay as is
- targetAlpha = me.fadedAlpha * e.ModalController_initialAlpha;
- }
- else if(e.ModalController_state == 1)
- {
- // zooming in
- targetOrigin = e.ModalController_initialOrigin;
- targetSize = e.ModalController_initialSize;
- targetAlpha = e.ModalController_initialAlpha;
- }
- else
- {
- // fading out
- if(f < 1)
- animating = 1;
- targetOrigin = e.Container_origin; // stay as is
- targetSize = e.Container_size; // stay as is
- targetAlpha = 0;
- }
-
- if(f == 1)
- {
- e.Container_origin = targetOrigin;
- e.Container_size = targetSize;
- me.setAlphaOf(me, e, targetAlpha);
- }
- else
- {
- e.Container_origin = e.Container_origin * prevFactor + targetOrigin * targetFactor;
- e.Container_size = e.Container_size * prevFactor + targetSize * targetFactor;
- me.setAlphaOf(me, e, e.Container_alpha * prevFactor + targetAlpha * targetFactor);
- }
- // assume: o == to * f_prev + X * (1 - f_prev)
- // make: o' = to * f + X * (1 - f)
- // --><