Beispiel #1
0
class test_StateArrayRefs_3(DelegatingInstanceOrExpr):  # testexpr_35b, _35c
    indices = range(3)
    heights = StateArrayRefs(Width, 0.0)
    direction = Arg(
        Vector, DX,
        "direction of permitted motion -- DZ is the goal but DX is easier for testing"
    )
    ### DX for initial test (testexpr_35b), then DZ (testexpr_35c)
    range = Option(tuple_Expr, None, doc="range limit of height")
    msg = Option(str, "drag along a line")

    def _height_dragger_for_index(self, index):
        stateref = StateArrayRefs_getitem_as_stateref(self.heights, index)
        #e change to self.heights.getitem_as_stateref(index)? self.heights._staterefs[index]?? self.heights[index]???
        newindex = ('_height_dragger_3_for_index', index)
        return self.Instance(
            _height_dragger_3(stateref,
                              self.direction,
                              sbar_text="%s (#%r)" % (
                                  self.msg,
                                  index,
                              ),
                              range=self.range), newindex)

    delegate = SimpleRow(
        MapListToExpr(
            _self._height_dragger_for_index,  ###k _self needed??
            indices,
            KLUGE_for_passing_expr_classes_as_functions_to_ArgExpr(
                SimpleColumn)),
        #e SimpleGrid? 2d form of MapListToExpr?
        ActionButton(
            _self.printit, "button: print state"
        )  ###e idea: define on special attr, let UI assemble debug info viewer
    )

    def printit(self):  #e can PrintAction do this for us?
        print[
            h.value for i, h in sorted_items(self.heights)
        ]  ###KLUGE, assumes they're StateRefs -- maybe just rename StateArray -> StateArrayRefs

    pass
Beispiel #2
0
class LocalVariable_StateRef(InstanceOrExpr): # guess, 061130
    # [moved here from controls.py, 061203; will probably become obs once State works]
    "return something which instantiates to something with .value which is settable state..."
    #e older name: StateRefFromIpath; is this almost the same as the proposed State() thing? it may differ in how to alter ipath
    # or some other arg saying where to store the ref, or in not letting you change how to store it (value encoding),
    # and worst, in whether it's an lval or not -- I think State is an lval (no need for .value) and this is a stateref.
    type = Arg(Type, Anything)
    defaultValue = ArgOrOption(Anything, None) ##e default of this should depend on type, in same way it does for Arg or Option
        # see comments in  about problems if this is a formula which uses anything usage-tracked -- same probably applies here.
    def get_value(self):
        #e should coerce this to self.type before returning it -- or add glue code wrt actual type, or....
        return self.transient_state.value ###e let transient_state not be the only option? does the stateplace even matter??
    def set_value(self, val): 
        self.transient_state.value = val #e should coerce that to self.type, or add glue code...
        return
    value = property(get_value, set_value)
    def _init_instance(self):
        super(LocalVariable_StateRef, self)._init_instance()
        set_default_attrs( self.transient_state, value = self.defaultValue) #e should coerce that to self.type
    pass
Beispiel #3
0
class TestIterator_alsoobsnow_nevertried(InstanceMacro):
    """
    simple iterator which makes two instances of the same arg
    """
    #e for debug, we should make args to pass to this which show their ipaths as text!
    thing = Arg(Maker(Widget)) # Maker? ExprFor? ProducerOf? Producer? Expr?
    w1 = Instance(thing)
        #k is number of evals correct in principle? internal uses of Instance assumed the expr was literal, were they wrong?
        # analyzing the code: this calls _i_inst with (an arg that evaluated to) getattr_Expr(_self, 'thing'),
        # and to instantiate that, it evals it, returning (I think) whatever self.thing is, which should be an instance of the arg.
        # This may make no sense but it's predicted that self.w1 and self.w2 should be instances, and the same one, of the arg.
        # that's wrong [thing's formula instantiates once too much, Instance(thing) once too little since I meant, I guess, I(*thing)]
        # , but it's not what I seem to be seeing, which is w1.width below running on either a non-instance
        # or something with a non-instance inside it. The non-instance is Translate, w1 should be a Boxed, so maybe that's consistent
        # if there's an error in Boxed. So I'm adding sanity checks to zome of: Boxed, Overlay, InstanceMacro, Translate. ###DOIT
##    print "w1 before ExprsMeta = %r" % (w1,) ###
    w2 = Instance(thing)
    # kluge since we don't have Row yet:
    _value = Overlay( w1, Translate(w2, V_expr(w1.width + 4 * PIXELS, 0,0)))
    pass
Beispiel #4
0
class checkbox_v3(
        InstanceMacro
):  ##e rename # note: this can do something checkbox_pref can't yet do -- take an external stateref
    stateref = Arg(StateRef,
                   None)  ### default? might not work with a default val yet
    ### IMPLEM: specify what external state to use, eg a prefs variable, PrefsKey_StateRef(displayOriginAxis_prefs_key)
    defaultValue = Option(bool, False)  ###BUG -- not used! [noticed 061215]
    ## var = State(bool, defaultValue)
    var = stateref.value
    ##    # print "var = %r" % (var,) # TypeError: 'module' object is not callable - on line that says on_press = Set(var, not_Expr(var) )
    ##        # solved: it's probably from above: import Set; from Set import something else but not Set
    _value = Highlightable(
        If(
            var,
            checkbox_image('mac_checkbox_on.png'),
            checkbox_image('mac_checkbox_off.png'),
        ),
        ## on_press = Set(var, not_Expr(var) ) # wanted (sort of), but doesn't work yet, as explained here:
        ## AssertionError:... <C_rule_for_formula at 0xff2de10 for 'var' in 'checkbox_v3'> should implement set_for_our_cls
        # ah, I was assuming "var = stateref.value" would alias var to obj.attr permitting set of obj.attr by set of var,
        # but of course, that should probably never be permitted to work, since it looks like we're changing self.var instead!
        # Unless, I either:
        # - implem a variant of "var = stateref.value"
        # - decide that since var would normally be unsettable when defined by a formula, that always aliasing it like that
        #   would be ok (often wanted, not too confusing).
        # PROBLEM WITH PERMITTING IT: you might start out var = State(), and it works to change self.var,
        # then change var to a formula, and forget you were directly setting it... causing an unwanted actual working set
        # of other state which you thought you were not touching or even able to touch.
        # SOLUTION:
        # - implem a variant of "var = stateref.value, sort of a "state alias"
        # - have a clear error message from this Set, suggesting to change that assignment to that alias form.
        # as of 061204 418p: tentatively decided I like that, but the alias variant syntax is not yet designed.
        # Maybe: ####@@@@
        # - var = Alias(stateref.value) ?? [sounds good]
        # - or just var = State(stateref.value), or is that too confusing?
        #   [yes, too confusing, that arg is for the type, and State is for new state, not an alias... latter is lesser problem]
        # - or var = StateRef(stateref.value)? no, it's an lval, not a stateref.
        on_press=Set(stateref.value, not_Expr(var))
        # kluge: see if this works (I predict it will) -- workaround of not yet having that alias form of "var = stateref.value"
    )
    pass  # end of class checkbox_v3
Beispiel #5
0
class Set(Action): # adding Set with arg1 an lval eg a getattr_Expr, 061204; untested, see testexpr_16
    """Set( variable, value) is an Action which sets variable to value.
    More precisely, variable should be an expr that can "evaluate to a settable lvalue",
    e.g. _self.attr or obj.attr or obj-expr[index-expr] [latter case is nim as of 061204],
    and value can be any ordinary evaluatable expr. When this Action is performed, it calls lval.set_to(val)
    for lval the current lvalue-object corresponding to variable, and val the current value of value.
       See also SetStateRefValue (deprecated).
    """
    var = LvalueArg(Anything) # LvalueArg is so macro-writers can pull in lvalue args themselves, easily; experimental; Option version?
    val = Arg(Anything)
    def _i_do_action(self):
        var = self.var
        val = self.val
        # print "%r: calling on our lval-object, %r.set_to(%r)" % (self, var , val)
        try:
            var.set_to( val) # .set_to is in api for lval-objects of this kind -- not the same kind as "exprs plus _self" (for now)
                ###e probably we should rename set_to -> set_value -- see StateRefInterface [070312]
        except:
            print "following exception in var.set_to( val) in %r concerns var = %r" % (self, var,)
            raise
        return
    pass
Beispiel #6
0
class ModelTreeNodeInterface(Interface):
    """
    Interface for a model tree node (something which can show up in a model tree view).
    Includes default compute method implems for use by type-coercion [which is nim]
    [see also ModelTreeNode_trivial_glue, and the node_xxx helper functions far below, for related code].
       WARNING: this class, itself, is not yet used except as a place to put this docstring.
    But the interface it describes is already in use, as a protocol involving the attrs described here.
    """
    _object = Arg(
        Anything,
        doc="an object we want to coerce into supporting this interface"
    )  ###k?? #e does it have to sound so nasty?
    # the recompute attrs in the interface, declared using Attr [nim] so they can include types and docstrings
    mt_node_id = Attr(
        Id,
        call_Expr(id, _object),
        doc="a unique nonrecyclable id for the node that object represents")
    ###BUG: id is wrong -- ipath would be closer (but is not really correct, see comments in def mt_node_id)
    mt_name = StateAttr(
        str,
        "",
        doc=
        "the name of a node in the MT; settable by the MT view (since editable in that UI)"
    )
    mt_kids = Attr(
        list_Expr, (),
        doc=
        "the list of visible kids, of all types, in order (client MT view will filter them)"
    )
    mt_openable = Attr(
        bool,
        False,
        doc=
        "whether this node should be shown as openable; if False, mt_kids is not asked for"
    )
    ##e (consider varying mt_openable default if node defines mt_kids, even if the sequence is empty)
    # (##e nothing here yet for type icons)
    pass
Beispiel #7
0
class PM_from_groups(
        DelegatingInstanceOrExpr
):  ###e refile into demo_ui or so, and call it on [make_polyline3d_PG(somearg)]
    "Make a Property Manager UI from a list of groupbox content widgets (eg columns of field editors) and other info."
    # args
    groups = Arg(list_Expr)
    #e in future these groups need to come with more attrs, like group titles
    # (WAIT, they already do have a title attr which we don't use here!),
    # whether they're closable and if so whether initially closed...
    # and they might include their own Boxed already...
    # the type decl might say we want a list of PropertyGroupBoxes,
    # with autoconversion of ParameterGroups to those...
    message = Option(
        str, "(PM message goes here)"
    )  # this has to be already split into lines, for now; all indentation is stripped

    # formulae
    def _C_use_message(self):
        lines = self.message.split('\n')
        lines = [line.strip() for line in lines]
        lines = filter(None, lines)
        return '\n'.join(lines)

    use_message = _self.use_message
    # appearance
    message_box = Boxed(TextRect(use_message), gap=0, bordercolor=yellow)
    group_box_column = MapListToExpr(
        KLUGE_for_passing_expr_classes_as_functions_to_ArgExpr(
            Boxed),  ###e change to a GroupBox, with a title from the group...
        groups,
        KLUGE_for_passing_expr_classes_as_functions_to_ArgExpr(SimpleColumn))
    delegate = SimpleColumn(
        Left(message_box),
        Left(group_box_column),
    )
    pass
Beispiel #8
0
class Clipped(InstanceOrExpr):
    """
    #doc
    """
    # note: we're not delegating anything.
    # e.g. the best lbox attrs for this are specified by the caller and relate to the planes passed to us.
    thing = Arg(Widget2D)
    planes = ArgOrOption(list_Expr(ClippingPlane))

    def draw(self):
        planes = self.planes
        assert len(planes) <= len(GL_CLIP_PLANE_table), \
               "no more than %d clipping planes are permitted" % \
               len(GL_CLIP_PLANE_table)
        # even if your OpenGL driver supports more -- no sense writing an expr that not everyone can draw!
        #    WARNING: this ignores the issue of nested Clipped constructs!
        # In fact, it assumes nothing in thing or above self uses any clipping planes.
        # (Not merely "assumes no more than 6 in all", because we hardcode which specific planes to use!)
        #    Worse, we don't even detect the error. Fixing the behavior is just as easy
        # (let graphical dynenv (self.env) know which planes are still available to any drawing-kid), so do that instead. ##e
        # Note that we might need to work inside a display list, and therefore we'd need to get the "next plane to use"
        # from an env which stays fixed (or from an env var which is changedtracked), not just from each draw call's caller
        # (i.e. a glpane attr).
        # enable the planes
        for i, plane in zip(range(len(planes)), planes):
            assert len(plane) == 4
            glEnable(GL_CLIP_PLANE_table[i])
            glClipPlane(GL_CLIP_PLANE_table[i], plane)
        # draw thing
        self.drawkid(self.thing)
        # disable the planes
        for i in range(len(planes)):
            glDisable(GL_CLIP_PLANE_table[i])
        return

    pass
Beispiel #9
0
class CenterY(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dy = (thing.bbottom - thing.btop) / 2.0
    delegate = Translate(thing, V_expr(0, dy, 0))
Beispiel #10
0
class DisplayListChunk( DelegatingInstanceOrExpr, SelfUsageTrackingMixin, SubUsageTrackingMixin ):
    """
    #doc
    [Note: the implicit value for SelfUsageTrackingMixin is the total drawing effect of calling our displist in immediate mode.
     This has an inval flag and invalidator, but we also have another pair of those for our display list's OpenGL contents,
     making this more complicated a use of that mixin than class Lval or its other uses.]
    [old long docstring and comment moved to outtakes file since unreviewed and partly redundant, 070102]
    """
    # default values of instance variables
    _direct_sublists_dict = 2 # intentional error if this default value is taken seriously
    contents_valid = False
    drawing_effects_valid = False
        # we don't yet have a specific flag for validity of sublist drawing effects (unknown when not contents_valid);
        # that doesn't matter for now; a useful optim someday would be a dict of all invalid-effects direct sublists #e
    
    # args
    delegate = Arg(Widget)
    
    # options
    debug_prints = ArgOrOption(str, None) # flag to do debug prints, and (unless a boolean) name for doing them

    def _C__debug_print_name(self): # compute self._debug_print_name
        """
        return False (meaning don't do debug prints), or a name string to prefix them with
        """
        # use this to say when we emit a calllist (and if so, immediate or into what other displist), and/or recompile our list
        #e and use in repr
        if self.debug_prints:
            if self.debug_prints == True:
                return "%r" % self ###BUG (suspected): this looks like an infrecur. Not sure if ever tested. [070110 comment]
            return str(self.debug_prints)
        return False
    
    def _init_instance(self):
        self._key = id(self) # set attribute to use as dict key (could probably use display list name, but it's not allocated yet)
        self.glpane = self.env.glpane #e refile into superclass??
        self._disabled = not hasattr(self.glpane, 'glGenLists')
        if self._disabled:
            # this should never happen after the merge of GLPane_overrider into GLPane done today [070110]
            print "bug: %r is disabled since its GLPane is missing required methods" % self
        return
        
    def _C_displist(self): # compute method for self.displist
        ### WARNING: this doesn't recycle displists when instances are remade at same ipath (but it probably should),
        # and it never frees them. To recycle them, just change it to use transient_state.
        # When we start using more than one GL Context which share display lists, we'll have to revise this somehow.
        #
        ### NOTE: usage tracking should turn up nothing -- we use nothing
        """
        allocate a new display list name (a 32-bit int) in our GL context
        """
        if self.displist_disabled(): # revised this cond (true more often), 070215
            printfyi("bug: why does .displist get requested in a disabled DisplayListChunk??") # (i never saw this)
            return 0
        
        self.glpane.makeCurrent() # not sure when this compute method might get called, so make sure our GL context is current
        displist = self.glpane.glGenLists(1) # allocate the display list name [#k does this do makeCurrent??]
        # make sure it's a nonzero int or long
        assert type(displist) in (type(1), type(1L))
        assert displist, "error: allocated displist was zero"
        if self._debug_print_name:
            print "%s: allocated display list name %r" % (self._debug_print_name, displist)
        return displist

    def __repr__(self):
        try:
            if not self._e_is_instance:
                return super(DisplayListChunk, self).__repr__()
            _debug_print_name = self._debug_print_name # only legal on an instance
        except:
            print "exception in self._debug_print_name discarded" #e print more, at least id(self), maybe traceback, if this happens
            # (but don't print self or you might infrecur!!)
            ##e can we print self.displist and/or self.delegate?
            return "<%s at %#x>" % (self.__class__.__name__, id(self))
        else:
            return "<%s(%s) at %#x>" % (self.__class__.__name__, _debug_print_name or "<no name>", id(self))
        pass

    def displist_disabled(self): #070215 split this out, modified it to notice _exprs__warpfuncs
        """
        Is the use of our displist (or of all displists) disabled at the moment?
        """
        return self._disabled or \
               debug_pref("disable DisplayListChunk?", Choice_boolean_False, prefs_key = True) or \
               getattr(self.env.glpane, '_exprs__warpfuncs', None) ###BUG: this will be too inefficient a response for nice dragging.
    
    def draw(self):
        """
        Basically, we draw by emitting glCallList, whether our caller is currently
        compiling another display list or executing OpenGL in immediate mode.
           But if our total drawing effects are invalid (i.e. our own list and/or some list it calls
        has invalid contents), we must do some extra things, and do them differently in those two cases.
           In immediate mode, if our own display list contents are invalid, we have to recompile it (without
        executing it) and only later emit the call, since compiling it is the only way to find out what other
        display lists it currently calls (when using the current widget expr .draw() API). Further, whether
        or not we recompiled it, we have to make sure any other lists it calls are valid, recompiling them
        if not, even though they too might call other lists we can't discover until we recompile them.
           Since OpenGL doesn't permit nested compiles of display lists, we use a helper function:
        given a set of display lists, make sure all of them are ok to call (by compiling zero or more of them,
        one at a time), extending this set recursively to all lists they indirectly call, as found out when
        recompiling them. This involves calling .draw methods of arbitrary widgets, with a glpane flag telling
        them we're compiling a display list. (In fact, we tell them its controller object, e.g. self,
        so they can record info that helps with later redrawing them for highlighting or transparency.)
           When not in immediate mode, it means we're inside the recursive algorithm described above,
        which is compiling some other display list that calls us. We can safely emit our glCallList before or after
        our other effects (since it's not executed immediately), but we also have to add ourselves to
        the set of displists directly called by whatever list is being compiled. (Doing that allows the
        recursive algorithm to add those to the set it needs to check for validity. That alg can optim by
        only doing that to the ones we know might be invalid, but it has to record them as sublists of
        the list being compiled whether or not we're valid now, since it might use that later when we're
        no longer valid.)
           We do all that via methods and/or private dynamic vars in self.glpane. ###doc which
           Note that the recursive algorithm may call us more than once. We should, of course, emit a glCallList
        every time, but get recompiled by the recursive algorithm at most once, whether that happens due to side effects
        here or in the algorithm or both. (Both might be possible, depending on what optims are implemented. ###k)
           Note that recursive display list calls are possible
        (due to bugs in client code), even though they are OpenGL errors if present when executed. (BTW, it's possible
        for cycles to exist transiently in display list contents without an error, if this only happens when
        some but not all display lists have been updated after a change. This needs no noticing or handling in the code.)
        """ 
        # docstring revised 070102.
        
        _debug_print_name = self._debug_print_name
        
        if self.displist_disabled():
            self.drawkid( self.delegate) ## self.delegate.draw()
            # I hope it's ok that this has no explicit effect on usage tracking or inval propogation... I think so.
            # It's equivalent to wrapping the whole thing in an If on this cond, so it must be ok.
            return
        
        self.displist
            # make sure we have a display list allocated
            # (this calls the compute method to allocate one if necessary)
            # [probably not needed explicitly, but might as well get it over with at the beginning]
            
            ###e NOTE: if someday we keep more than one displist, compiled under different drawing conditions in dynenv
            # (e.g. different effective values of glpane._exprs__warpfuncs),
            # then some or all of our attrs need splitting by the case of which displist to use,
            # and we also have to avoid usage-tracking the attrs that eval that case in the same way
            # as those we use when compiling displists. (As if we're If(cond, displistchunk1, displistchunk2),
            #  but also making sure nothing in displistchunk1 tracks those same attrs in a way we see as our own usage,
            #  or if it does, making sure we don't subscribe inval of a displist to that, by adding new code
            #  to end_tracking_usage to handle those usages specially, having known what they were by tracking cond, perhaps --
            #  or by explicit description, in case cond also tracks other stuff which doesn't show up in its value.
            #  Or another way, if the cond-value-attrs are special (e.g. glpane._exprs__warpfuncs),
            #  is for them to not be natively usage-tracked, but only when we eval cond (not sure this is ok re outsider tracking
            #  of them -- maybe better to track them except when we set a specialcase dynenv flag next to them,
            #  which they notice to decide whether to track uses, which we set when inside the specific case for the cond-value.)
            #  [070215]

        # are we being compiled into another display list?
        parent_dlist = self.glpane.compiling_displist_owned_by # note: a dlist owner or None, not a dlist name
        
        if parent_dlist:
            # We're being compiled into a display list (owned by parent_dlist); tell parent that its list calls ours.
            # (Note: even if we're fully valid now, we have to tell it,
            #  since it uses this info not only now if we're invalid, but later,
            #  when we might have become invalid. If we ever have a concept of
            #  our content and/or drawing effects being "finalized", we can optim
            #  in that case, by reducing what we report here.)
            if _debug_print_name:
                print "%s: compiling glCallList into parent list %r" % (_debug_print_name, parent_dlist)

            parent_dlist.__you_called_dlist( self) #e optim: inline this
                # (note: this will also make sure the alg recompiles us and whatever lists we turn out to call,
                #  before calling any list that calls us, if our drawing effects are not valid now.)
            
        elif self.glpane.compiling_displist:
            print "warning: compiling dlist %r with no owner" % self.glpane.compiling_displist
            #e If this ever happens, decide then whether anything but glCallList is needed.
            # (Can it happen when compiling a "fixed display list"? Not likely if we define that using a widget expr.)
            
        else:
            # immediate mode -- do all needed recompiles before emitting the glCallList,
            # and make sure glpane will be updated if anything used by our total drawing effect changes.
            if _debug_print_name:
                print "%s: prepare to emit glCallList in immediate mode" % (_debug_print_name, )
            
            self.glpane.ensure_dlist_ready_to_call( self) # (this might print "compiling glCallList" for sublists)
                # note: does transclose starting with self, calls _recompile_if_needed_and_return_sublists_dict
            self.track_use() # defined in SelfUsageTrackingMixin; compare to class Lval
                # This makes sure the GLPane itself (or whatever GL context we're drawing into, if it has proper usage tracking)
                # knows it needs to redraw if our drawing effects change.
                # Note: this draw method only does track_use in immediate mode (since it would be wrong otherwise),
                # but when compiling displists, it can be done by the external recursive algorithm via track_use_of_drawing_effects.
        if _debug_print_name:
            print "%s: emit glCallList(%r)" % (_debug_print_name, self.displist)
        self.do_glCallList() #e optim: inline this
        return # from draw

        # some old comments which might still be useful:
            
            # 061023 comments: analogous to Lval.get_value, both in .draw always being such, and in what's happening in following code.

            # Another issue - intermediate levels in a formula might need no lval objs, only ordinary compute calls,
            # unless they have something to memoize or inval at that level... do ordinary draw methods, when shared,
            # need this (their own capturing of inval flag, one for opengl and one for total effect,
            # and their own pair of usage lists too, one of called lists which can be scanned)??

    # this doesn't work due to quirks of Python:
    ## track_use_of_drawing_effects = track_use # this is semipublic; track_use itself (defined in SelfUsageTrackingMixin) is private
    # so rather than slow it down by a def,
    # I'll just rename the calls track_use but comment them as really track_use_of_drawing_effects

    def _your_drawing_effects_are_valid(self): ##e should inline as optim
        """
        """
        assert self.contents_valid
            # this failed 070104 with the exception shown in long string below, when I used clear "button" (070103 kluge) on one node...
            # theory: the world.nodelist change (by clear button run inside draw method, which is illegal -- that's the kluge)
            # invalidated it right when it was being recompiled (or just after, but before the overall recomp alg sent this call).
            # So that kluge has to go [later: it's gone],
            # and the underlying error of changing an input to an ongoing recompute has to be better detected. ####e
        self.drawing_effects_valid = True
        return

# the exception mentioned above: 
    """
atom_debug: fyi: <OneTimeSubsList(<LvalForState(<World#16291(i)>|transient.nodelist|('world', (0, (0, 'NullIpath')))) at 0x101a7b98>) at 0x10583850>'s 
event already occurred, fulfilling new subs 
<bound method usage_tracker_obj.standard_inval of <usage_tracker_obj(<DisplayListChunk(<no name>) at 0x111b7670>) at 0x112086e8>> immediately: 

[atom.py:414] [GLPane.py:1847] [GLPane.py:1884] [testmode.py:67] [testdraw.py:251] [GLPane_overrider.py:127]
[GLPane_overrider.py:138] [GLPane_overrider.py:298] [testmode.py:75] [testdraw.py:275] [testdraw.py:385]
[testdraw.py:350] [testdraw.py:384] [testdraw.py:530] [test.py:1231] [Overlay.py:57] [Overlay.py:57]
[Overlay.py:57] [DisplayListChunk.py:286] [DisplayListChunk.py:124] [state_utils.py:156] [DisplayListChunk.py:116]
[DisplayListChunk.py:358] [changes.py:352] [changes.py:421] [changes.py:72]

exception in testdraw.py's drawfunc call ignored: exceptions.AssertionError:

[testdraw.py:350] [testdraw.py:384] [testdraw.py:530] [test.py:1231] [Overlay.py:57] [Overlay.py:57]
[Overlay.py:57] [DisplayListChunk.py:286] [DisplayListChunk.py:127] [DisplayListChunk.py:314]
"""
    def __you_called_dlist(self, dlist):
        self.__new_sublists_dict[ dlist._key ] = dlist
            # note: this will intentionally fail if called at wrong time, since self.__new_sublists_dict won't be a dict then
        return
    
    def _recompile_if_needed_and_return_sublists_dict(self):
        """
        [private helper method for glpane.ensure_dlist_ready_to_call()]
        Ensure updatedness of our displist's contents (i.e. the OpenGL instructions last emitted for it)
        and of our record of its direct sublists (a dict of owners of other displists it directly calls).
        Return the dict of direct sublists.
           As an optim [mostly nim], it's ok to return a subset of that, which includes all direct sublists
        whose drawing effects might be invalid. (In particular, if our own drawing effects are valid,
        except perhaps for our own displist's contents, it's ok to return {}. [That's the part of this optim we do.])
        """ 
        # doc revised 070102
        if not self.contents_valid:
            # we need to recompile our own displist.
            if self._debug_print_name:
                print "%s: compiling our displist(%r)" % (self._debug_print_name, self.displist)
            
            self._direct_sublists_dict = 3 # intentional error if this temporary value is used as a dict
                # (note: this might detect the error of a recursive direct or indirect call -- untested ##k)
            self.__new_sublists_dict = new_sublists_dict = {}
                # this is added to by draw methods of owners of display lists we call
            mc = self.begin_tracking_usage()
                # Note: we use this twice here, for different implicit values, which is ok since it doesn't store anything on self.
                # [#e i should make these non-methods to clarify that.]
                # This begin/end pair is to track whatever affects the OpenGL commands we compile;
                # the one below is to track the total drawing effects of the display lists called during that
                # (or more generally, any other drawing effects not included in that, but tracking for any other
                #  kinds of effects, like contents of textures we draw to the screen ### WHICH MIGHT MATTER, is nim).
                #
                # Note that track_use and track_inval do NOT have that property -- they store self.__subslist.
            try:
                self.recompile_our_displist()
                    # render our contents into our displist using glNewList, self.drawkid( self.delegate), glEndList
                    # note: has try/except so always does endlist ##e make it tell us if error but no exception??
            finally:
                self.contents_valid = True
                    # Q: is it ok that we do this now but caller might look at it?
                    # A: yes, since caller never needs to see it -- it's effectively private.
                self.end_tracking_usage( mc, self.invalidate_contents) # same invalidator even if exception during recompile or its draw
                self._direct_sublists_dict = dict(new_sublists_dict)
                    #e optim: this copy is only for bug-safety in case something kept a ref and modifies it later
                self.__new_sublists_dict = 4 # illegal dict value

            mc2 = self.begin_tracking_usage() # this tracks how our drawing effects depend on those of the sublists we call
            try:
                for sublist in self._direct_sublists_dict.itervalues():
                    sublist.track_use() # really track_use_of_drawing_effects (note: that's tracked into the global env, as always for track_use)
            finally:
                self.end_tracking_usage( mc2, self.invalidate_drawing_effects )
                    # this subscribes invalidate_drawing_effects to inval of total effects of all sublists
                    # (effectively including indirectly called ones too);
                    # the only thing it doesn't cover is subscribing it to inval of our own displist's contents,
                    # so we manually call it in invalidate_contents.
        if self.drawing_effects_valid:
            if debug_pref("DisplayListChunk: permit optim 070204?", Choice_boolean_False):
                ###BUG: this old optim seems to cause the bug 070203 -- I don't know why, but disabling it seems to fix the bug ###k
                print "doing optim 070204"#e and listnames [#e only print if the optim makes a difference?]
                return {} # optim; only possible when self.contents_valid,
                    # tho if we had a separate flag for sublist contents alone,
                    # we could correctly use that here as a better optim #e
            else:
                pass ## print "not doing optim 070204"#e and listnames
        return self._direct_sublists_dict

    def invalidate_contents(self):
        """
        [private] 
        called when something changes which might affect 
        the sequence of OpenGL commands that should be compiled into self.displist
        """
        if self.contents_valid:
            self.contents_valid = False
            self.invalidate_drawing_effects()
        else:
            # this clause would not be needed except for fear of bugs; it detects/complains/works around certain bugs.
            if self.drawing_effects_valid:
                print "bug: self.drawing_effects_valid when not self.contents_valid. Error, but invalidate_drawing_effects anyway."
                self.invalidate_drawing_effects()
            pass
        return
    
    def invalidate_drawing_effects(self):
        # note: compare to class Lval
        if self.drawing_effects_valid:
            self.drawing_effects_valid = False
            # propogate inval to whoever used our drawing effects
            self.track_inval() # (defined in SelfUsageTrackingMixin)
        return

    def recompile_our_displist(self):
        """
        [private] call glNewList/draw/glEndList in the appropriate way, 
        but do no usage tracking or valid-setting
        """
        glpane = self.glpane
        displist = self.displist
        glpane.glNewList(displist, GL_COMPILE, owner = self)
            # note: not normally a glpane method, but we'll turn all gl calls into methods so that glpane can intercept
            # the ones it wants to (e.g. in this case, so it can update glpane.compiling_displist)
            # note: we have no correct way to use GL_COMPILE_AND_EXECUTE, as explained in draw docstring
        try:
            self.drawkid( self.delegate) ## self.delegate.draw()
        except:
            print_compact_traceback("exception while compiling display list for %r ignored, but terminates the list: " % self )
            ###e should restore both stack depths and as much gl state as we can
            # (but what if the list contents are not *supposed* to preserve stack depth? then it'd be better to imitate their intent re depths)
            pass
        glpane.glEndList(displist)
            # note: glEndList doesn't normally have an arg, but this arg lets glpane version of that method do more error-checking
        return
    
    def do_glCallList(self):
        """
        emit a call of our display list, whether or not we're called in immediate mode
        """
        self.glpane.glCallList( self.displist)
        return
    
    pass # end of class DisplayListChunk
Beispiel #11
0
class Right(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dx = -thing.bright
    delegate = Translate(thing, V_expr(dx, 0, 0))
Beispiel #12
0
class Left(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dx = +thing.bleft
    delegate = Translate(thing, V_expr(dx, 0, 0))
Beispiel #13
0
class BottomCenter(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dx = (thing.bleft - thing.bright) / 2.0
    dy = +thing.bbottom
    delegate = Translate(thing, V_expr(dx, dy, 0))
Beispiel #14
0
class TopCenter(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dx = (thing.bleft - thing.bright) / 2.0
    dy = -thing.btop
    delegate = Translate(thing, V_expr(dx, dy, 0))
Beispiel #15
0
class ChoiceButton(InstanceMacro):
    """ChoiceButton(choiceval, choiceref, content, background, background_off) [most args optional]
    displays and permits control of a choice variable stored externally in choiceref,
    looking like Overlay(background, content) or Overlay(background_off, content)
    when its own choice value is chosen or unchosen (ie equal or unequal to the stored one), respectively.
       Most args are optional with useful defaults, or can be given as simpler convenience types (eg colors or text);
    all args but choiceval can be given as named options, which is useful for customization.
       (Example: it's useful to put several of these with the same choiceref but different choicevals into a Column.
    This can be done by mapping one customized variant over a list of choicevals.)
       The choosing-action occurs on_press of entire thing -- this is not yet changeable
    (to other kinds of button actions), but should be. #e
    """
    # args
    choiceval = Arg(Anything)
    #e declare it as having to be constant per-Instance? Or can it legally vary?? I guess it could;
    # and I guess it's no error, just weird, for two of these (eg in a column) to share the same choiceval;
    # in fact, if they're physically separated it's not even weird.

    sbar_text = Option(str, format_Expr(
        "%s", _self.choiceval))  # mouseover text for statusbar

    choiceref = ArgOrOption(StateRef)  ###k need value-type??

    content = ArgOrOption(
        stubtype, TextRect(format_Expr("%s", _self.choiceval))
    )  # Widget2D or something "displayable" in one (eg text or color); defaults to displayed choiceval;
    # can caller pass a formula in terms of the other options to _self?
    # Maybe, but not by saying _self! _this(ChoiceButton) == _my? [yes -- _my is now implemented, 061205]

    background = ArgOrOption(
        stubtype, Rect(_self.width, _self.height, lightblue)
    )  # Widget2D, or color (used in Rect a bit larger than content)

    background_off = ArgOrOption(stubtype, Spacer(
        _self.width, _self.height))  # ditto, defaults to transparent
    ##k problem: what we want is to compute an lbox and then use this here in the spacer... or align the content... or ....
    ##e note that a lot of people find it more convenient to pass around a size, or even pass around a rect,
    # than to always work with 4 or 6 rect-related attrs...

    # formulae
    chosen = eq_Expr(choiceref.value, choiceval)  #k
    ## print "chosen is",chosen

    ###k assume useful conversions of named options happened already
    ###e use _value; is it as simple as renaming it delegate and using DelegatingMixin?? Can InstanceMacro do it for us??
    # [if we use one of those, be careful not to inherit from Widget2D here, due to its lbox defaults!]
    _value = Highlightable(
        Overlay(
            SpacerFor(Boxed(content)),
            # kluge to make room around content in _self.width and _self.height,
            # and make those non-circular; WRONG because won't be properly aligned with backgrounds,
            # even if content itself would be;
            # could fix by shifting, but better to figure out how to have better rectlike size options ###e
            Overlay(  ###KLUGE since "Overlay is a stub which only works with exactly two args"
                If(chosen, background, background_off), content),
        ),
        ## old code: on_press = SetStateRefValue(choiceref, choiceval),
        # try this code 061211 1113a -- it works, use it:
        on_press=Set(choiceref.value, choiceval),
        ##e probably best to say Set(choiceref.value, choiceval), but I think that's nim -- not sure --
        # should retest it after Set is revised later today to work with arg1 being lval eg getattr_Expr [061204]
        sbar_text=sbar_text)
    pass  # end of class ChoiceButton
Beispiel #16
0
class DrawInCorner_projection(DelegatingInstanceOrExpr):
    """
    [DEPRECATED for general use -- use DrawInCorner instead.]
    
    This is a variant of DrawInCorner which works by changing the projection matrix,
    and which has several bugs/niys. It only works for the default corner argument,
    and any Highlightables in its main argument (delegate) only work properly for
    highlighting if they are given the option projection = True (which is not the
    default, for efficiency reasons [this may change on 081202]).

    Its usefulness is that it's the only expr (as of 070405) which changes the
    projection matrix for the subexprs it draws, so it's the only good test of
    Highlightable(projection = True).
    """
    # Note: renamed from DrawInCorner_NOTWORKING_VERSION to DrawInCorner_projection on 070405,
    # since tests show that Highlightable(projection=True) has been working inside it for awhile.
    #
    # But to make it the usual implem of DrawInCorner would require:
    # - a good reason (like pixel alignment bugs after trackballing, in the other implem -- not yet annoying enough);
    # - args fixed up to match that one;
    # - implem the other corners -- only the default one works now, I think;
    # - make it unnecessary to say projection = True to embedded Highlightables,
    #   using either a GLPane flag (with special provisions for display lists,
    #   which might need two variants depending on that flag),
    #   or a change of default value of that option,
    #   or a change of algorithm in Highlightable.

    delegate = Arg(Widget2D)
    corner = Arg(int, LOWER_RIGHT)

    def draw(self):
        # this code is modified from drawcompass

        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadIdentity()

        glMatrixMode(
            GL_PROJECTION
        )  # WARNING: we're now in nonstandard matrixmode (for sake of gluPickMatrix and glOrtho -- needed??##k)
        glPushMatrix()
        glLoadIdentity()

        try:
            glpane = self.env.glpane
            aspect = glpane.aspect  # revised by bruce 070919, UNTESTED
            corner = self.corner
            delegate = self.delegate

            ###e should get glpane to do this for us (ie call a method in it to do this if necessary)
            # (this code is copied from it)
            glselect = glpane.current_glselect
            if glselect:
                # print "%r (ipath %r) setting up gluPickMatrix" % (self, self.ipath)
                x, y, w, h = glselect
                gluPickMatrix(
                    x,
                    y,
                    w,
                    h,
                    glGetIntegerv(
                        GL_VIEWPORT
                    )  #k is this arg needed? it might be the default...
                )

            # the first three cases here are still ###WRONG
            if corner == UPPER_RIGHT:
                glOrtho(-50 * aspect, 5.5 * aspect, -50, 5.5, -5,
                        500)  # Upper Right
            elif corner == UPPER_LEFT:
                glOrtho(-5 * aspect, 50.5 * aspect, -50, 5.5, -5,
                        500)  # Upper Left
            elif corner == LOWER_LEFT:
                glOrtho(-5 * aspect, 50.5 * aspect, -5, 50.5, -5,
                        500)  # Lower Left
            else:
                ## glOrtho(-50 * aspect, 5.5 * aspect, -5, 50.5,  -5, 500) # Lower Right
                ## glOrtho(-50 * aspect, 0, 0, 50,  -5, 500) # Lower Right [used now] -- x from -50 * aspect to 0, y (bot to top) from 0 to 50
                glOrtho(-glpane.width * PIXELS, 0, 0, glpane.height * PIXELS,
                        -5, 500)
                # approximately right for the checkbox, but I ought to count pixels to be sure (note, PIXELS is a pretty inexact number)

            glMatrixMode(
                GL_MODELVIEW
            )  ###k guess 061210 at possible bugfix (and obviously needed in general) --
            # do this last to leave the matrixmode standard
            # (status of bugs & fixes unclear -- hard to test since even Highlightable(projection=True) w/o any change to
            # projection matrix (test _9cx) doesn't work!)
            offset = (-delegate.bright, delegate.bbottom
                      )  # only correct for LOWER_RIGHT
            glTranslatef(offset[0], offset[1], 0)
            self.drawkid(delegate)  ## delegate.draw()

        finally:
            glMatrixMode(GL_PROJECTION)
            glPopMatrix()
            glMatrixMode(
                GL_MODELVIEW
            )  # be sure to do this last, to leave the matrixmode standard
            glPopMatrix()

        return

    pass  # end of class DrawInCorner_projection
Beispiel #17
0
class If_expr(
        InstanceMacro
):  #e refile ### WAIT A MINUTE, why does Exprs.py think it needs to be an OpExpr? for getattr & call?
    #### NOT YET REVIEWED FOR EVAL_REFORM 070117
    cond = Arg(
        bool
    )  # WARNING: this is effectively a public attr; none of these argnames will be delegated to the value (I think)
    _then = Arg(Anything)
    _else = Arg(
        Anything, None
    )  # note: the None default probably won't work here; the callers presently pass a TextRect

    # update 070914: I added a kluge in _e_argval_If_expr to try to make this default work
    # (not using the fact that it's declared here except to permit expr init when it's not passed)
    def _C__value(self):
        if self.cond:
            # digr: I mistakenly thought _then & _else ipaths were same, in some debugging e.g. printing _self.ipath,
            # since I said _self where I meant _this(Highlightable).
            # THAT'S GOING TO BE A COMMON PROBLEM -- need to rethink the jargon...
            # maybe let _this.attr work (find innermost Instance with capitalized classname??) [061121]
            return self._then
        else:
            return self._else
        pass

    # addendum 061212:
    # The above is enough for If(cond, InstanceOrExpr1(), InstanceOrExpr2()), since it delegates to one of them as needed.
    # but it's not enough for use an as OpExpr that needs to eval, as in
    # testexpr_9fx2 = Rect(color = If_expr(_my.env.glpane.in_drag, blue, lightblue))() (or the same with color as arg3).
    # For that, I think we need an eval method which returns a different value in each case... OTOH that might cause trouble
    # when it's used to instantiate. Which calls which, of _e_eval and _e_make_in and things that call either one?
    # The one that can say "REJECTED using _e_make_in case" is _CV__i_instance_CVdict -- only happens on toplevel exprs in class attr
    # assignments I think, maybe only when Instance/Arg/Option is involved. In the IorE class, _e_make_in is primitive
    # and _e_eval calls it -- after saying printnim("Instance eval doesn't yet handle If"). So that's what we want to fix here:
    # (439p: This affected many or all uses of If, but note that _e_make_in is probably never or almost never called,
    #  so that is not surprising in hindsight.)
    def _e_eval(self, env, ipath):  # added 061212
        ## super method: return self._e_make_in(env, ipath)
        # note, this might be WRONG if the toplevel assignment of a class formula is an If.
        # We might want to permit it and change _i_instance or _CV__i_instance_CVdict to do usage-tracking of this eval... ###e
        # otoh this might all be superceded by the "planned new eval/instantiate code", for which this change of today
        # is a related pre-experiment. [061212]
        ## res = self._value ##k? this fails because self is an expr, and env probably contains _self to help that (in which to eval cond),
        # but we're not doing it right... #### LOGIC BUG -- enough pain to do that to call into Q this method of doing it....
        # or can be easy if we do what OpExpr._e_eval would do?
        condval = self._e_argval_If_expr(0, env, ipath)
        if condval:
            res = self._e_argval_If_expr(1, env, ipath)
        else:
            res = self._e_argval_If_expr(2, env, ipath)
        ## print "is this right?: %r gets cond %r, evals to %r" % (self, condval, res)
        # This happens in a lot of existing If-examples, but seems ok, for reasons not fully understood. (But see comment above 439p.)
        # For test results & discussion see comments in '061127 coding log' (bruce's g5) dated 061212 410p.
        return res

    def _e_argval_If_expr(
        self, i, env, ipath
    ):  # modified from OpExpr (I don't want to try making OpExpr a superclass right now)
        # _e_argval is not normally defined in InstanceOrExpr, which is important --
        # we don't want to override anything in there unwittingly. To be safe, I renamed it.
        ## args = self._e_args
        args = self._e_args  # I guess this is correct -- self.cond etc would prematurely eval or instantiate them i think (#k not sure!)
        if i == 2 and len(args) == 2:
            # KLUGE: special case to make default _else clause work
            return None
        res = args[i]._e_eval(env, (i, ipath))
        return res

    pass
Beispiel #18
0
class polyline3d(
        InstanceOrExpr
):  # WARNING [070319]: duplicated code, demo_drag.py and demo_draw_on_surface.py [modified a bit]
    """A graphical object with an extendable (or resettable from outside I guess) list of points,
    and a kid (end1) (supplied, but optional (leaving it out is ###UNTESTED)) that can serve as a drag handle by default.
    (And which also picks up a cmenu from self. (kluge!))
    Also some Options, see the code.
    """
    # Note [070307]: this class will be superceded by class Polyline in demo_polyline.py,
    # and the code that uses it below (eg the add_point call) will be superseded by other code in that file.
    #
    ###BUGS: doesn't set color, depends on luck. end1 is not fully part of it so putting cmenu on it will be hard.
    # could use cmenu to set the options.
    # end1 might be in MT directly and also be our kid (not necessarily wrong, caller needn't add it to MT).
    # when drawing on sphere, long line segs can go inside it and not be seen.
    points = State(
        list_Expr,
        [])  ###k probably wrong way to say the value should be a list
    ##    end1arg = Arg(StubType,None)
    ##    end1 = Instance(eval_Expr( call_Expr(end1arg.copy,)( color = green) ))###HACK - works except color is ignored and orig obscures copy
    end1 = Arg(
        StubType,
        None,
        doc=
        "KLUGE arg: optional externally supplied drag-handle, also is given our cmenu by direct mod"
    )
    closed = Option(bool, False, doc="whether to draw it as a closed loop")
    _closed_state = State(bool, closed)  ####KLUGE, needs OptionState
    relative = Option(
        bool,
        True,
        doc=
        "whether to position it relative to the center of self.end1 (if it has one)"
    )

    def _init_instance(self):
        end1 = self.end1
        if end1:
            end1.cmenu_maker = self

    def _C__use_relative(self):
        "compute self._use_relative (whether to use the relative option)"
        if self.relative:
            try:
                center = self.end1.center
                return True
            except:
                #e print?
                return False
        return False

    def _C_origin(self):  #070307 renamed this to origin from center
        if self._use_relative:
            return self.end1.center  # this can vary!
        return ORIGIN
##    center = _self.origin #k might not be needed -- guessing it's not, 070307

    def add_point(self, pos):
        "add a point at the given 3d position"
        pos = pos - self.origin
        self.points = self.points + [
            pos
        ]  ### INEFFICIENT, but need to use '+' for now to make sure it's change-tracked

    def draw(self):
        ###k is it wrong to draw both a kid and some opengl stuff?? not really, just suboptimal if opengl stuff takes long (re rendering.py)
        self.drawkid(self.end1)  # end1 node
        if self._closed_state:
            glBegin(GL_LINE_LOOP
                    )  # note: nothing sets color. see drawline for how.
            # in practice it's thin and dark gray - just by luck.
        else:
            glBegin(GL_LINE_STRIP)
        if self._use_relative:
            # general case - but also include origin (end1.center) as first point!
            origin = self.origin
            glVertex3fv(origin)
            for pos in self.points:
                glVertex3fv(pos + origin)
        else:
            # optim - but not equivalent since don't include origin!
            for pos in self.points:
                glVertex3fv(pos)
        glEnd()
        #e option to also draw dots on the points [useful if we're made differently, one click per point; and they might be draggable #e]
        return

    def make_selobj_cmenu_items(self, menu_spec, highlightable):
        """Add self-specific context menu items to <menu_spec> list when self is the selobj (or its delegate(?)... ###doc better).
        Only works if this obj (self) gets passed to Highlightable's cmenu_maker option (which DraggableObject(self) will do).
        [For more examples, see this method as implemented in chem.py, jigs*.py in cad/src.]
        """
        menu_spec.extend([
            (
                "polyline3d", noop, 'disabled'
            ),  # or 'checked' or 'unchecked'; item = None for separator; submenu possible
        ])

    pass  # end of class polyline3d
Beispiel #19
0
class CenterX(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dx = (thing.bleft - thing.bright) / 2.0
    delegate = Translate(thing, V_expr(dx, 0, 0))
Beispiel #20
0
class Bottom(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dy = +thing.bbottom
    delegate = Translate(thing, V_expr(0, dy, 0))
Beispiel #21
0
class Top(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dy = -thing.btop
    delegate = Translate(thing, V_expr(0, dy, 0))
Beispiel #22
0
class xxx_drag_behavior(
        DragBehavior
):  # revised 070316; on 070318 removed comments that were copied into version _3
    """a drag behavior which moves the original hitpoint along a line,
    storing only its 1d-position-offset along the line's direction
    [noting that the hitpoint is not necessarily equal to the moved object's origin]
    [#doc better]
    """
    # args
    highlightable = Arg(
        DraggableObject
    )  # kluge; revised 070316, delegate -> highlightable [works no worse than before [same bug as before]]
    # [but it's misnamed -- it has to be a DraggableObject since we modify its .motion]
    ###e rename, but what is it for?
    posn_parameter_ref = Arg(StateRef,
                             doc="where the variable height is stored")
    ###e rename
    constrain_to_line = Arg(
        Ray,
        Ray(ORIGIN, DY),
        doc="the line/ray on which the height is interpreted as a position")

    ###e rename: constraint_line? line_to_constrain_to? constrain_to_this_line?
    # dflt_expr is just for testing #e remove it

    def current_event_mouseray(self):
        p0 = self.highlightable.current_event_mousepoint(
            depth=0.0)  # nearest depth ###k
        p1 = self.highlightable.current_event_mousepoint(
            depth=1.0)  # farthest depth ###k
        return Ray(
            p0, p1 - p0
        )  #e passing just p1 should be ok too, but both forms can't work unless p0,p1 are typed objects...

    def on_press(self):
        self.startpoint = self.highlightable.current_event_mousepoint(
        )  # the touched point on the visible object (hitpoint)
        self.offset = self.startpoint - (
            ORIGIN + self.highlightable.motion
        )  #k maybe ok for now, but check whether sensible in long run
        self.line = self.constrain_to_line + self.offset  # the line the hitpoint is on (assuming self.motion already obeyed the constraint)

    def on_drag(self):
        # Note: we can assume this is a "real drag" (not one which is too short to count), due to how we are called.
        mouseray = self.current_event_mouseray()
        ##        self._cmd_drag_from_to( oldpoint, point) # use Draggable interface cmd on self
        # ie self.delta_stateref.value = self.delta_stateref.value + (p2 - p1)
        ## def drag_mouseray_from_to(self, oldray, newray): # sort of like _cmd_from_to (sp?) in other eg code
        ## "[part of an interface XXX related to drag behaviors]"
        k = self.line.closest_pt_params_to_ray(mouseray)
        if k is not None:
            # store k
            self.posn_parameter_ref.value = k  ####e by analogy with DraggableObject, should we perhaps save this side effect until the end?
            # compute new posn from k
            self.highlightable.motion = self.constrain_to_line.posn_from_params(
                k)  #e review renaming, since we are asking it for a 3-tuple
            ####### LOGIC BUG: what causes self.motion to initially come from this formula, not from our own state?
            # maybe don't use DraggableObject at all? [or as initial kluge, just let initial motion and initial height both be 0]
        return

    def on_release(self):
        pass

    pass  # end of class xxx_drag_behavior
Beispiel #23
0
class DrawInCorner(DelegatingInstanceOrExpr):
    """
    DrawInCorner( thing, (-1,-1)) draws thing in the lower left corner of the screen
    (positioning thing so that its layout box's lower left corner nests directly into that corner of the screen).
    The depth can be specified by the option want_depth (between 0.0 and 1.0), which by default is 0.01 (very near the front).
    [###UNTESTED: it may be that non-default depths have never been tested.]

    The "corner" can be any corner, or any edge, or the center of the screen;
    it can be specified as a 2nd argument (x,y), or by the option corner = (x,y),
    where x can be -1, 0, or 1 (for left, center, or right respectively)
    and y can be -1, 0, or 1 (for bottom, center, or top).

    For the corners, the abbreviations defined in prefs_constants (small ints called UPPER_RIGHT, UPPER_LEFT,
    LOWER_LEFT, LOWER_RIGHT) are also permitted (and for convenience can also be imported from this class's source file).

    When thing does not need to touch a screen boundary (in one or both dimensions),
    it is not shifted at all, meaning its local origin is aligned with the specified position in that dimension.
    For drawing in an edge or the center, consider wrapping thing in Center or the like to modify this.
    (Without this feature, DrawInCorner( thing, (0,0)) would be equivalent to DrawInCorner( Center(thing), (0,0)).)

    ###BUG: The current implem (as of 070210) probably doesn't work properly after coordinate changes inside display lists.
    """
    ##e should we reverse the arg order? [recent suggestion as of 070302]
    delegate = Arg(Widget2D)
    corner = ArgOrOption(
        int,
        LOWER_RIGHT,
        doc=
        "the corner/edge/center to draw in, as named int or 2-tuple; see class docstring for details"
    )
    # note: semi-misnamed option, since it can also be an edge or the center
    ###KLUGE: type spec of 'int' is wrong -- we also allow it to be a pair of ints for x,y "symbolic posn" respectively
    want_depth = Option(
        float, 0.01
    )  # this choice is nearer than cov_depth (I think!) but doesn't preclude 3D effects (I hope).

    def draw(self):
        if self.delegate is None:
            # 070210 -- but I'm not sure if this is a complete ###KLUGE, or good but ought to be done more generally,
            # or if it would be better to do it totally differently by instantiating None into something like Spacer(). ##k
            return

        glMatrixMode(GL_MODELVIEW)  # not needed
        glPushMatrix()
        glLoadIdentity()
        try:
            glpane = self.env.glpane
            aspect = glpane.aspect  # revised by bruce 070919
            corner = self.corner
            delegate = self.delegate
            want_depth = self.want_depth
            # note about cov_depth:
            ## self.near = 0.25
            ## self.far = 12.0
            # so I predict cov_depth is 0.75 / 11.75 == 0.063829787234042548
            # but let's print it from a place that computes it, and see.
            # ... hmm, only place under that name is in selectMode.py, and that prints 0.765957458814 -- I bet it's something
            # different, but not sure. ###k (doesn't matter for now)

            # modified from _setup_modelview:

            saveplace = self.transient_state  # see if this fixes the bug 061211 1117a mentioned below -- it does, use it.
            # BUG (probably not related to this code, but not known for sure):
            # mousewheel zoom makes checkboxes inside DrawInCorner
            # either not highlight, or if they are close enough to
            # the center of the screen (I guess), highlight in the
            # wrong size and place. For more info and a partial theory,
            # see the 081202 update in DisplayListChunk.py docstring.
            # Before I realized the connection to DisplayListChunk,
            # I tried using saveplace = self.per_frame_state instead of
            # self.transient_state above, but that had no effect on the bug.
            # That was before I fixed some bugs in same_vals related to
            # numpy.ndarray, when I was plagued with mysterious behavior
            # from those in my debug code (since solved), but I tried it
            # again afterwards and it still doesn't fix this bug, which
            # makes sense if my partial theory about it is true.
            #
            # In principle (unrelated to this bug), I'm dubious we're
            # storing this state in the right place, but I won't change
            # it for now (see related older comments below).
            #
            # Note: I fixed the bug in another way, by changing
            # Highlightable's projection option to default True.
            # [bruce 081202]

            if glpane.current_glselect or (0 and 'KLUGE' and hasattr(
                    saveplace, '_saved_stuff')):
                # kluge did make it faster; still slow, and confounded by the highlighting-delay bug;
                # now I fixed that bug, and now it seems only normally slow for this module -- ok for now.

                # when that cond is false, we have a nonstandard projection matrix
                # (see also the related comments in save_coords_if_safe in Highlightable.py)
                # [bruce 081204 comment]

                x1, y1, z1 = saveplace._saved_stuff  # this is needed to make highlighting work!
                ###BUG [061211 1117a; fixed now, see above, using saveplace = self.transient_state]:
                # if we click on an object in testexpr_15d (with DrawInCorner used for other objs in the testbed)
                # before it has a chance to show its highlighted form, at least after a recent reload, we get an attrerror here.
                # Easy to repeat in the test conditions mentioned (on g5). Not sure how it can affect a different obj (self)
                # than the one clicked on too quickly. Best fix would be to let glpane give us the requested info,
                # which is usually the same for all callers anyway, and the same across reloads (just not across resizes).
                # But it does depend on want_depth, and (via gluUnProject) on the current modelview coords
                # (and projection coords if we ever changed them). So it's not completely clear how to combine ease, efficiency,
                # and safety, for that optim in general, even w/o needing this bugfix.
                #    But the bug is easy to hit, so needs a soon fix... maybe memoize it with a key corresponding to your own
                # assumed choice of modelview coords and want_depth? Or maybe enough to put it into the transient_state? TRY THAT. works.
                if _DEBUG_SAVED_STUFF:
                    print "_DEBUG_SAVED_STUFF: retrieved", x1, y1, z1
            else:
                x1, y1, z1 = saveplace._saved_stuff = \
                             gluUnProject(glpane.width, glpane.height, want_depth)
                # max x and y, i.e. right top
                # (note, to get the min x and y we'd want to pass (0, 0, want_depth),
                #  since these are windows coords -- (0, 0) is bottom left corner (not center))
                #
                # Note: Using gluUnProject is probably better than knowing and reversing _setup_projection,
                # since it doesn't depend on knowing the setup code, except meaning of glpane height & width attrs,
                # and knowing that origin is centered between them and 0.
                if _DEBUG_SAVED_STUFF:
                    print "_DEBUG_SAVED_STUFF: saved", x1, y1, z1


##            print x1,y1,z1
# use glScale to compensate for zoom * scale in _setup_projection,
# for error in PIXELS, and for want_depth != cov_depth
            x1wish = glpane.width / 2.0 * PIXELS  # / 2.0 because in these coords, screen center indeed has x == y == 0
            r = x1 / x1wish
            glScale(r, r, r)
            ##            x1 /= r
            ##            y1 /= r
            z1 /= r
            # now the following might work except for z, so fix z here
            glTranslatef(0.0, 0.0, z1)
            del x1, y1  # not presently used
            if _DEBUG_SAVED_STUFF:
                print "_DEBUG_SAVED_STUFF:     r = %r, translated z by z1 == %r" % (
                    r, z1)

            # I don't think we need to usage-track glpane height & width (or scale or zoomFactor etc)
            # since we'll redraw when those change, and redo this calc every time we draw.
            # The only exception would be if we're rendering into a display list.
            # I don't know if this code (gluUnProject) would even work in that case.
            # [I think I wrote a similar comment in some other file earlier today. #k]

            # move to desired corner, and align it with same corner of lbox
            # (#e could use an alignment prim for the corner if we had one)

            if corner in corner_abbrevs:
                # normalize how corner is expressed, into a 2-tuple of +-1's
                corner = corner_abbrevs[corner]

            x, y = corner

            if x == -1:  # left
                x_offset = -glpane.width / 2.0 * PIXELS + delegate.bleft
            elif x == +1:  # right
                x_offset = +glpane.width / 2.0 * PIXELS - delegate.bright
            elif x == 0:  # center(x)
                x_offset = 0
                # note: before 070210 this was (+ delegate.bleft - delegate.bright) / 2.0,
                # which has an unwanted (since unavoidable) centering effect; use explicit Center if desired.
            else:
                print "invalid corner", corner  ###
                raise ValueError, "invalid corner %r" % (corner, )

            if y == -1:  # bottom
                y_offset = -glpane.height / 2.0 * PIXELS + delegate.bbottom
            elif y == +1:  # top
                y_offset = +glpane.height / 2.0 * PIXELS - delegate.btop
            elif y == 0:  # center(y)
                y_offset = 0
                # note: # note: before 070210 this was (+ delegate.bbottom - delegate.btop) / 2.0
            else:
                print "invalid corner", corner  ###
                raise ValueError, "invalid corner %r" % (corner, )

            offset = (x_offset, y_offset)
            glTranslatef(offset[0], offset[1], 0.0)

            if _DEBUG_SAVED_STUFF:
                print "_DEBUG_SAVED_STUFF:     offset =", offset

            self.drawkid(delegate)  ## delegate.draw()

        finally:
            glMatrixMode(GL_MODELVIEW)  # not needed
            glPopMatrix()

        return

    pass  # end of class DrawInCorner
Beispiel #24
0
class AlignmentExpr(DelegatingInstanceOrExpr):  # doesn't work yet, see below
    thing = Arg(Widget2D)
    dx = 0  # override in some subclasses
    dy = 0
    delegate = Translate(thing, V_expr(dx, dy, 0))
    pass
Beispiel #25
0
class Sphere_ExampleModelNode(ModelNode):
    """
    A sphere.
    """
    pos = StateArg(Position, ORIGIN) ###IMPLEM StateArg , StateArgOrOption
        #e or can all arg/option formulas be treated as state, if we want them to be? (no, decl needed)
        #e or can/should the decl "this is changeable, ie state" as a flag option to the Arg macro?
        #e can it be set to a new *formula*, not just a new constant value? (for constraint purposes)
        #e - if so, does this require a decl to say it's possible, or is it always possible? (note: it affects mmp writing and copy)

    if 0:
        # StateArg might be equivalent to this (except for the name to use in the Arg if it matters, e.g. for StateOption):
        _orig_pos = Arg(Position, ORIGIN) #e can we pass an index to override '_orig_pos' if it matters?
        pos = State(Position, _orig_pos) # see similar code in demo_drag (in class Vertex I think)

    radius = StateArg(Width, 1)
    color = StateArgOrOption(Color, gray)
##    def draw_unpicked(self):
##        ###KLUGE: this is copied from Sphere.draw in Rect.py.
##        ##e Instead, we should define and cache a real Sphere using self-formulas, and draw that,
##        # and delegate to it for lbox as well.
##        from drawer import drawsphere # drawsphere(color, pos, radius, detailLevel)
##        drawsphere(self.fix_color(self.color), self.center, self.radius, self.detailLevel) # some of this won't work ######IMPLEM
    # so is using Sphere hard? maybe not:
    _value = Sphere(pos, radius, color) # and something to delegate to it... but only for drawing and lbox, delegation by ModelNode??
        # wait, why would we delegate lbox? if we're a Node does that mean we have a position? if lbox is used, does that mean we're
        # drawn by a graphic parent, not as the appearance of some node? For now, assume we won't delegate lbox. OTOH can some
        # graphic thing use a model object as shorthand for "whatever that looks like in the present env"? Without wrapping it??
        # If so, that might lead to our desire to delegate lbox, and everything else in some to-be-formalized "3dgraphics API".
    #e but how would we make that depend on the current display mode? just look at self.env? Or is that part of the model?
        # what about instances of drawables -- they depend on env, maybe they are not fixed for a given model object like we are!!!
        # should we grab env out of glpane when Node.draw is called?

        ###LOGIC PROBLEM 1: Group.draw assumes there's 1-1 correspondence between subnodes in MT and subnodes drawn.
        # POSSIBLE EASY FIX: override Group.draw for our own kind of Grouplike objects. At least, it can modify drawing env,
        # even if it also usually calls the subnode draw methods. BTW we could pass env to draw as a new optional arg.

        ###LOGIC PROBLEM 2: we'd really rather make a parallel drawable (perhaps a tree) and draw that, not call draw on subnodes
        # directly. POSSIBLE EASY FIX: just do it -- don't call draw on subnodes directly, assume they're kids of main drawable.
        # Then Node.draw only gets called at the top of "our kind of Group". That can even work for subnodes not of our type,
        # if we turn them into drawables of a simple kind, by wrapping them with "draw old-style Node using old API".

        ### PROBLEM 3: what if we are drawn multiply in one screen, how does it work?
        # SOLUTION: the Node.draw is not our normal draw api -- that's "find view of this model object and draw it"
        # (specific to env, ipath, other things). The Node.draw is mainly used when legacy modes (not testmode) draw the object.
        # Those can only draw it in one place so it doesn't matter. (Hmm, what if we define a Grouplike node which draws whatever's
        # under it in more than one place? It'd have to work by altering global coords before calling Node.draw. It could pass
        # optional env and ipath args, or whatever, to permit smart nodes to create Instances of their appearance...
        # think this through. ###e)    (It's almost like we just want to add new dynamic args to Node.draw and start using that...
        # in order to coexist in mixed ways with old-style Nodes. They should be dynamic so they pass through old-style Nodes
        # unchanged and are still seen by their new-style Node children. But does this work when there's >1 glpane?
        # BTW, what about drawing with Atoms or Bonds (old drawables, but not Nodes)??
        # I'm not even sure their .draw API is the same. It might be, or could be made to be.)

        ### WORSE PROBLEM 4: what if >1 MT, with different MT-views of one model object? Letting model obj be its own MTNode
        # is a scheme only one of the MTs can use, or that requires the MT-views to be identical (even for value of node.open).
        # If we had multiple MTs we'd want each to have its own set of Nodes made to view our model objects.
        # That would be a fundamentally better scheme anyway. So we'll want it for our own newer MTs (like the ones in the GLPane).
        # So will we want it from the start?
        # Or let it coexist with "model obj can give you a node for another MT, and at same time, be one for "the MT""?

        # ... I guess it now seems like making a separate Node proxy is best, and only using it for this old-MT interface
        # but noting the multiple purposes of that (all the ones listed in the module docstring, unless testmode is running
        # and not using the old rendering code on the assy). For awhile, even in testmode, save file will still use assy.tree, etc.
        # So we'll keep needing to interface with these old APIs through the "old MT view". But we'll like having new views too,
        # incl new-MT (in glpane or not) and new-graphics view (various dispmodes).

        # SO FIRST FIGURE OUT THE GENERAL WAY TO GET VIEW OBJECTS FROM MODEL OBJECTS. Some sort of caching recomputing dict?
        # preferably with adaptive keys, that automatically generalize when subkeys are not used in main expr or subexprs...
        # but for now, ok to ignore that optim (esp if we redecide the key for each subexpr, and some *know* they don't use
        # some parts of the most general key). Compare to what's in demo_MT, texture_holder, CL.
        #
        # ... re all that, see RecomputingMemoDict (written just now, not yet used). ###e
        # The idea is to use it to map objects into images (views) of themselves (with keys containing objs and other data),
        # where instances are images of exprs, view objs are instances of model objs
        # (whether the view objs are Nodes (old MT) or MTViews (new one) or _3DViews(?)), glue code wrapped things of those things.
        # But in some cases we'd like the dict val to permanent -- in that case, use MemoDict and a wayfunc that recomputes internally
        # and delegates to what it recomputes (or forwards to it if it becomes final, as an optim). This might be true for glue code,
        # not sure about viewers. We might like to say which style we prefer in each case (as if part of the key).
        #
        # Note: current direct uses of MemoDict are texture holders and MTView; of LvalDict2 are subinstances -- and any others?
        # StatePlaces -- but they don't make use of the recomputing ability.
    pass
Beispiel #26
0
class TopLeft(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dx = +thing.bleft
    dy = -thing.btop
    delegate = Translate(thing, V_expr(dx, dy, 0))
Beispiel #27
0
class ActionButton(DelegatingInstanceOrExpr):  # 070104 quick prototype
    "ActionButton(command, text) is something the user can press to run command, which looks like a button."
    # args/options
    command = Arg(Action)  #e default which prints?
    text = Arg(str, "<do it>"
               )  #e default text should be extracted from the command somehow
    button = Arg(
        Widget2D, Rect(15. * PIXELS)
    )  # can it be left out so only text label is used? ideally we'd have text with special border...
    enabled = Option(
        bool, True
    )  # whether the button should look enabled, and whether the command will run when the button is operated
    # formulae
    use_label = TextRect(text)  ## TextRect(text,1,20)###e revise
    plain_button = CenterY(button)
    highlighted_button = Boxed(
        plain_button,  # note: despite the name, this is only shown as the highlighted form when enabled is true
        bordercolor=
        blue,  # should color adapt to bg? is it a bad idea to put this over bg rather than over button?
        borderthickness=1.5 * PIXELS,
        gap=1 * PIXELS,
    )  ###k ????   -- note, this doesn't include the label -- ok?
    plain = DisplayListChunk(SimpleRow(
        plain_button, CenterY(use_label)))  # align = CenterY is nim
    highlighted = DisplayListChunk(
        SimpleRow(highlighted_button, CenterY(use_label), pixelgap=0.5))
    #k ok to wrap with DisplayListChunk? [seems so]
    ### KLUGE: without the pixelgap adjustment (to this particular weird-looking value, i guess),
    # the label moves to the right when highlighted, due to the Boxed being used to position it in the row.
    ### BUG: CenterY is not perfectly working. Guess -- lbox for TextRect is slightly wrong.
    ### IDEA: make the borderthickness for Boxed negative so the border is over the edge of the plain button. Might look better.
    ##e Note: we have no "pressed" appearance, since by the next time we get drawn, the command is already drawn and we ought to be
    # back to normal. Someday we should do a transient incremental redraw of just this button, with a "pressed and acting" appearance,
    # which can then go back to normal when the operation completes and does a regular full redraw.
    # Alternatively, we could switch to using buttons with an on_release_in action only,
    # and then have ordinarily-drawn pressed etc looks. [070227 comment]
    # update 070305: let's try to fix that:

    # appearances for optional willdoit-flicker (confirms unambiguously that the button was hit and will do something) [070307]
    # [ideally the computation & side effects could overlap the willdoit flicker in time,
    #  but they don't now, which is one reason the flicker is optional]
    incr_drawable_willdo1 = Instance(
        SimpleRow(highlighted_button(bordercolor=yellow),
                  pixelgap=0.5))  # label not needed here
    incr_drawable_willdo2 = Instance(
        SimpleRow(highlighted_button(bordercolor=blue), pixelgap=0.5))
    # note: yellow/blue (matching the usual ending & starting colors which bracket the flicker) looks much better than black/white

    # what it looks like while we're computing/doing its effects:
    incr_drawable_doing = Instance(
        SimpleRow(
            highlighted_button(bordercolor=orange),
            ## CenterY(use_label), [removed -- see comment for why -- might be added back]
            pixelgap=0.5))
    # orange warns you that it's not yet done, is also bright & active for action;
    ### UI FLAW: the orange/yellow distinction is annoying, so it's really only desirable for debugging,
    # since it shows that the instantiation time is significant but only happens on the first use of a button.
    # Probably the distinction (and its redraw happening at all) should be a debug_pref or so. ###FIX
    # (But if there is no distinction, we may want to be sure to redraw the label now if there is any chance it can be different --
    #  but in current code there's not, since we haven't changed state it might depend on by the time we draw it.
    #  BTW I wonder if redrawing the label (i.e. instantiating this instance of it) ever takes significant time itself?? #k)

    # what it looks like while we're redrawing (after finishing its internal effects):
    incr_drawable_done = Instance(
        SimpleRow(highlighted_button(bordercolor=yellow),
                  pixelgap=0.5))  # label not needed here

    # yellow means done -- not sure makes sense -- note green means "can do" in some controls

    def doit(self):
        """This runs when the user clicks on the button.
        WARNING: it's NOT just self.do_action() (the public method self's clients, like scripts, can call to do the same action) --
        it calls that, but it also has graphical effects.
        [It may or may not be public (in the Action interface) in the end. If it is, it'll be renamed. #e]
        """
        if self.enabled:
            # do some incremental drawing [new feature 070305, revised 070307]
            ###BUG (in some client code of this class):
            # this won't be able to make clear button quickly show it's disabled until client code is revised and maybe selobj-bugfixed ###DOIT
            if debug_pref(
                    "testmode: ActionButton willdoit-flicker?",
                    # When set, this flickers the button, like how the mac confirms a menu item choice.
                    # Conclusion after testing: it works fine, and usually looks ok,
                    # but is redundant with "yellow during redraw",
                    # so as long as that's slow enough to see, this has no point and is also making it even slower,
                    # so leave it turned off by default.
                    Choice_boolean_False,
                    prefs_key='A9 devel/exprs/action flicker'):
                # works [retest###], but I won't make it True by default [070307]
                ##e someday do this in a way that does not tie up the thread during this, e.g. by letting paintGL do it;
                # for now it's just experimental for its graphics effects and as a speed test,
                # and will probably be turned off after testing
                for i in range(4):
                    if i % 2 == 0:
                        self.draw_incrementally(self.incr_drawable_willdo1)
                    else:
                        self.draw_incrementally(self.incr_drawable_willdo2)
                    # print i, # very fast
                    # todo: delay, if needed to make this visible -- using time.time to delay only if draw timing was not long enough
                    # (with no delay it's almost too fast too see -- sometime I should write the code to measure the actual speed)
                    # (for now assume it's always very fast, so just delay a fixed amount using time.sleep)
                    time.sleep(1.0 / 3 / 4)  # 1/3 sec, spread over 4 sleeps
            self.draw_incrementally(
                self.incr_drawable_doing
            )  # this method runs in the Highlightable made in delegate
            print "ActionButton: doing %r for %r" % (self.text, self
                                                     )  ### remove self?
            ##e optim note: this shows self is a different obj each time (at least for make dna cyl button)...
            # I guess this is due to dna_ribbon_view_toolcorner_expr_maker being a function that makes an expr
            # which runs again at least on every use of the button (maybe more -- not sure exactly how often).
            # Should fix that (and it's not this file's fault -- just that the print stmt above reveals the problem).
            self.do_action()
            self.draw_incrementally(self.incr_drawable_done)
            pass
        else:
            print "ActionButton: not enabled, so not doing %r for %r" % (
                self.text, self)  # remove when works [reenabled 070307 ####]
            pass
        return

    def do_action(self):
        "#doc -- public, also used internally; see doit comment for doc, for now"
        res = self.command()
        if res is not None:
            print "unexpected: %r cmd %r retval was not None: %r" % (
                self,
                self.text,
                res,
            )  #e remove if happens legitimately
        return

    ###e refile these:
    def draw_incrementally(
            self, thing):  #070307 #e refile (as for next method below)
        "#doc"
        self._incrementally_draw_OpenGL(
            thing.draw
        )  #e or call a variant method of thing, which defaults to thing.draw?? nah, use an env var?

    def _incrementally_draw_OpenGL(
        self, func
    ):  #070307 #e rename ###e refile into IorE someday, and into Highlightable for now, i think
        """helper method for incremental drawing by user event handling methods (not part of self.draw called by paintGL).
        [#doc better]
        func should contain OpenGL commands for incrementally drawing, in self's coords (but not the swapbuffers at the end).
           Guess at a requirement within func: [which should be removed and is prob not real now, see below]
        # don't use drawkid! (because we're not inside a draw method)
        # (but will this cause trouble for draw methods inside this?? ### NEEDS REVIEW)
        [but instead we might as well make sure that drawkid's parent-seeing alg will not be messed up, since it'll be used
        inside whatever subthing draws we call, anyway]
        """

        ###e undefined in API so far: what if func says "draw later" (eg for transparency) -- do we do all that too, before we return??
        # guess: yes, but we'll need special drawing-env settings to tell primitives inside func that we're doing incremental drawing,
        # since it'll affect things like whether it's ok to write into the depth buffer for transparent objs obscuring visible ones
        # (useful for glselect code but would mess up subsequent incr drawing).
        def func1(self=self, func=func):
            res = func()
            self.env.glpane.swapBuffers()  # update display [needed]
            return res

        ran_already_flag, funcres = self.run_OpenGL_in_local_coords(func1)
        # note: this runs in self or first delegate that's a Highlightable, for now; that determines its gl state & coordsys
        assert ran_already_flag
        return funcres

    #e should we change to doing the action on_release_in, rather than on_press?
    delegate = Highlightable(
        plain,  ##e should this depend on enabled? probably yes, but probably the caller has to pass in the disabled form.
        ###e at least for the Mac, maybe it also ought to depend on whether the application is active (frontmost) and will respond to clicks.
        If(
            enabled, highlighted, plain
        ),  # revised 070109 to depend on enabled [#k does this cause the delegate expr itself to be remade??]
        on_press=_self.doit,
        # note: there was a bug in the prior form of this, "on_press = command" -- command to do should depend on enabled --
        ##e but i'm not sure if If(enabled,command,None) will work properly ###k TRY IT -- nevermind, using _self.doit now [070208]
        sbar_text=text
        #e should sbar_text depend on enabled?? yes, but need to revise callers then too -- some of which make the text depend on it
    )
    pass  # end of class ActionButton
Beispiel #28
0
class CenterLeft(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dx = +thing.bleft
    dy = (thing.bbottom - thing.btop) / 2.0
    delegate = Translate(thing, V_expr(dx, dy, 0))
Beispiel #29
0
class Overlay(InstanceOrExpr, DelegatingMixin):
    "Overlay has the size of its first arg, but draws all its args in the same place, with the same origin."
    # Note: we can't inherit from Widget2D, or we'd fail to delegate
    # e.g. bright to self.delegate, and pick up the default value instead!
    # I'm not yet sure whether the proper fix is to handle those defaults in some other way
    # (e.g. as a last-resort delegate of some sort -- maybe we could say right here (to a fancier
    #  version of DelegatingMixin), if you don't find the attr in self.delegate, look in Widget2D).
    # See also comments in InstanceMacro, about the same issue for it.
    # [061210 grabbing SimpleColumn's scheme for permitting up to 10 args, though ArgList is nim]
    a0 = Arg(
        Widget2D, None
    )  # so it's not a bug to call it with no args, as when applying it to a list of no elts [061205]
    a1 = Arg(Widget2D, None)
    a2 = Arg(Widget2D, None)
    a3 = Arg(Widget2D, None)
    a4 = Arg(Widget2D, None)
    a5 = Arg(Widget2D, None)
    a6 = Arg(Widget2D, None)
    a7 = Arg(Widget2D, None)
    a8 = Arg(Widget2D, None)
    a9 = Arg(Widget2D, None)
    a10 = Arg(Widget2D, None)
    a11 = Arg(Widget2D, None)
    args = list_Expr(
        a0,
        a1,
        a2,
        a3,
        a4,
        a5,
        a6,
        a7,
        a8,
        a9,
        a10,  # could say or_Expr(a0, Spacer(0)) but here is not where it matters
        and_Expr(a11, TextRect("too many args in Overlay")))

    delegate = or_Expr(a0, Spacer(0))  ## _self.a0 # needed by DelegatingMixin

    ##    args = list_Expr(arg0, arg1) # not sure if [arg0, arg1] would work, but I doubt it --
    ###e should make it work sometime, if possible (e.g. by delving inside all literal list ns-values in ExprsMeta)
    #e add an option to make each element slightly closer, maybe just as a depth increment? makes hover highlighting more complicated...
    def draw(self):
        args = self.args  # this order is correct since we set glDepthFunc to GL_LEQUAL (not GL_LESS)
        for a in args:
            self.drawkid(a)
            #e We'd like this to work properly for little filled polys drawn over big ones.
            # We might need something like z translation or depth offset or "decal mode"(??).
            # [later 070404: "decal mode" is probably unrelated -- GL_DECAL is for combining a texture with a non-textured color/alpha,
            #  not related to using depth buffer when resulting textured object is drawn. Is "decal" used to mean anything else?? #k]
            # Different depth test would be best [done now -- GL_LEQUAL], but roundoff error might make it wrong...
            # This is definitely needed for overdrawing like that to work, but it's low priority for now.
            # Callers can kluge it using Closer, though that's imperfect in perspective mode (or when viewpoint is rotated).
            # [Or glDepthRange, now used for highlight drawing in GLPane as of 070921.]

    pass  # Overlay
Beispiel #30
0
class BottomLeft(DelegatingInstanceOrExpr):
    thing = Arg(Widget2D)
    dx = +thing.bleft
    dy = +thing.bbottom
    delegate = Translate(thing, V_expr(dx, dy, 0))