AnimationPlayer* play(Animation* animation, double startTime)
 {
     AnimationPlayer* player = timeline->play(animation);
     player->setStartTime(startTime * 1000);
     player->update(TimingUpdateOnDemand);
     return player;
 }
Exemplo n.º 2
0
void AnimationTimeline::serviceAnimations(TimingUpdateReason reason)
{
    TRACE_EVENT0("blink", "AnimationTimeline::serviceAnimations");

    m_timing->cancelWake();

    double timeToNextEffect = std::numeric_limits<double>::infinity();

    Vector<RawPtr<AnimationPlayer> > players;
    players.reserveInitialCapacity(m_playersNeedingUpdate.size());
    for (HashSet<RefPtr<AnimationPlayer> >::iterator it = m_playersNeedingUpdate.begin(); it != m_playersNeedingUpdate.end(); ++it)
        players.append(it->get());

    std::sort(players.begin(), players.end(), AnimationPlayer::hasLowerPriority);

    for (size_t i = 0; i < players.size(); ++i) {
        AnimationPlayer* player = players[i];
        if (player->update(reason))
            timeToNextEffect = std::min(timeToNextEffect, player->timeToEffectChange());
        else
            m_playersNeedingUpdate.remove(player);
    }

    if (timeToNextEffect < s_minimumDelay)
        m_timing->serviceOnNextFrame();
    else if (timeToNextEffect != std::numeric_limits<double>::infinity())
        m_timing->wakeAfter(timeToNextEffect - s_minimumDelay);

    ASSERT(!hasOutdatedAnimationPlayer());
}
void CompositorPendingAnimations::notifyCompositorAnimationStarted(double monotonicAnimationStartTime)
{
    for (size_t i = 0; i < m_waitingForCompositorAnimationStart.size(); ++i) {
        AnimationPlayer* player = m_waitingForCompositorAnimationStart[i].get();
        player->setStartTimeInternal(monotonicAnimationStartTime - player->timeline()->zeroTime(), true);
    }

    m_waitingForCompositorAnimationStart.clear();
}
Exemplo n.º 4
0
AnimationPlayer* AnimationTimeline::play(AnimationNode* child)
{
    if (!m_document)
        return 0;
    AnimationPlayer* player = createAnimationPlayer(child);
    player->setStartTimeInternal(effectiveTime());
    m_document->compositorPendingAnimations().add(player);
    return player;
}
bool CompositorAnimations::startAnimationOnCompositor(const Element& element, int group, double startTime, double timeOffset, const Timing& timing, const AnimationPlayer& player, const AnimationEffect& effect, Vector<int>& startedAnimationIds, double playerPlaybackRate)
{
    ASSERT(startedAnimationIds.isEmpty());
    ASSERT(isCandidateForAnimationOnCompositor(timing, element, &player, effect, playerPlaybackRate));
    ASSERT(canStartAnimationOnCompositor(element));

    const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(effect);

    DeprecatedPaintLayer* layer = toLayoutBoxModelObject(element.layoutObject())->layer();
    ASSERT(layer);

    Vector<OwnPtr<WebCompositorAnimation>> animations;
    CompositorAnimationsImpl::getAnimationOnCompositor(timing, group, startTime, timeOffset, keyframeEffect, animations, playerPlaybackRate);
    ASSERT(!animations.isEmpty());
    for (auto& animation : animations) {
        int id = animation->id();
        if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) {
            WebCompositorAnimationPlayer* compositorPlayer = player.compositorPlayer();
            ASSERT(compositorPlayer);
            compositorPlayer->addAnimation(animation.leakPtr());
        } else if (!layer->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer()->addAnimation(animation.release())) {
            // FIXME: We should know ahead of time whether these animations can be started.
            for (int startedAnimationId : startedAnimationIds)
                cancelAnimationOnCompositor(element, player, startedAnimationId);
            startedAnimationIds.clear();
            return false;
        }
        startedAnimationIds.append(id);
    }
    ASSERT(!startedAnimationIds.isEmpty());
    return true;
}
Exemplo n.º 6
0
const AtomicString CSSAnimations::getAnimationNameForInspector(const AnimationPlayer& player)
{
    for (const auto& it : m_animations) {
        if (it.value->sequenceNumber() == player.sequenceNumber())
            return it.key;
    }
    return nullAtom;
}
Exemplo n.º 7
0
String AnimationTree::get_configuration_warning() const {

	String warning = Node::get_configuration_warning();

	if (!root.is_valid()) {
		if (warning != String()) {
			warning += "\n";
		}
		warning += TTR("A root AnimationNode for the graph is not set.");
	}

	if (!has_node(animation_player)) {

		if (warning != String()) {
			warning += "\n";
		}

		warning += TTR("Path to an AnimationPlayer node containing animations is not set.");
		return warning;
	}

	AnimationPlayer *player = Object::cast_to<AnimationPlayer>(get_node(animation_player));

	if (!player) {
		if (warning != String()) {
			warning += "\n";
		}

		warning += TTR("Path set for AnimationPlayer does not lead to an AnimationPlayer node.");
		return warning;
	}

	if (!player->has_node(player->get_root())) {
		if (warning != String()) {
			warning += "\n";
		}

		warning += TTR("AnimationPlayer root is not a valid node.");
		return warning;
	}

	return warning;
}
Exemplo n.º 8
0
// http://w3c.github.io/web-animations/#in-play
bool
KeyframeEffectReadonly::IsInPlay(const AnimationPlayer& aPlayer) const
{
  if (IsFinishedTransition() ||
      aPlayer.PlayState() == AnimationPlayState::Finished) {
    return false;
  }

  return GetComputedTiming().mPhase == ComputedTiming::AnimationPhase_Active;
}
Exemplo n.º 9
0
void VisibilityEnabler::_change_node_state(Node *p_node, bool p_enabled) {

	ERR_FAIL_COND(!nodes.has(p_node));

	{
		RigidBody *rb = Object::cast_to<RigidBody>(p_node);
		if (rb)

			rb->set_sleeping(!p_enabled);
	}

	{
		AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);

		if (ap) {

			ap->set_active(p_enabled);
		}
	}
}
Exemplo n.º 10
0
void VisibilityEnabler2D::_change_node_state(Node *p_node, bool p_enabled) {

	ERR_FAIL_COND(!nodes.has(p_node));

	{
		RigidBody2D *rb = Object::cast_to<RigidBody2D>(p_node);
		if (rb) {

			rb->set_sleeping(!p_enabled);
		}
	}

	{
		AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);

		if (ap) {

			ap->set_active(p_enabled);
		}
	}
	{
		AnimatedSprite *as = Object::cast_to<AnimatedSprite>(p_node);

		if (as) {

			if (p_enabled)
				as->play();
			else
				as->stop();
		}
	}

	{
		Particles2D *ps = Object::cast_to<Particles2D>(p_node);

		if (ps) {

			ps->set_emitting(p_enabled);
		}
	}
}
Exemplo n.º 11
0
// http://w3c.github.io/web-animations/#current
bool
KeyframeEffectReadonly::IsCurrent(const AnimationPlayer& aPlayer) const
{
  if (IsFinishedTransition() ||
      aPlayer.PlayState() == AnimationPlayState::Finished) {
    return false;
  }

  ComputedTiming computedTiming = GetComputedTiming();
  return computedTiming.mPhase == ComputedTiming::AnimationPhase_Before ||
         computedTiming.mPhase == ComputedTiming::AnimationPhase_Active;
}
void CompositorAnimations::attachCompositedLayers(const Element& element, const AnimationPlayer& player)
{
    ASSERT(element.layoutObject());

    DeprecatedPaintLayer* layer = toLayoutBoxModelObject(element.layoutObject())->layer();
    ASSERT(layer);

    WebCompositorAnimationPlayer* compositorPlayer = player.compositorPlayer();
    ASSERT(compositorPlayer);

    ASSERT(layer->compositedDeprecatedPaintLayerMapping());
    compositorPlayer->attachLayer(layer->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer()->platformLayer());
}
void CompositorAnimations::cancelIncompatibleAnimationsOnCompositor(const Element& targetElement, const AnimationPlayer& playerToAdd, const AnimationEffect& effectToAdd)
{
    const bool affectsOpacity = effectToAdd.affects(CSSPropertyOpacity);
    const bool affectsTransform = effectToAdd.affects(CSSPropertyTransform);
    const bool affectsFilter = effectToAdd.affects(CSSPropertyWebkitFilter);

    if (!targetElement.hasAnimations())
        return;

    ElementAnimations* elementAnimations = targetElement.elementAnimations();
    ASSERT(elementAnimations);

    for (const auto& entry : elementAnimations->players()) {
        AnimationPlayer* attachedPlayer = entry.key;
        if (!considerPlayerAsIncompatible(*attachedPlayer, playerToAdd))
            continue;

        if ((affectsOpacity && attachedPlayer->affects(targetElement, CSSPropertyOpacity))
            || (affectsTransform && attachedPlayer->affects(targetElement, CSSPropertyTransform))
            || (affectsFilter && attachedPlayer->affects(targetElement, CSSPropertyWebkitFilter)))
            attachedPlayer->cancelAnimationOnCompositor();
    }
}
Exemplo n.º 14
0
Vector<String> AnimationTreeEditor::get_animation_list() {

	if (!singleton->is_visible()) {
		return Vector<String>();
	}

	AnimationTree *tree = singleton->tree;
	if (!tree || !tree->has_node(tree->get_animation_player()))
		return Vector<String>();

	AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(tree->get_node(tree->get_animation_player()));

	if (!ap)
		return Vector<String>();

	List<StringName> anims;
	ap->get_animation_list(&anims);
	Vector<String> ret;
	for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
		ret.push_back(E->get());
	}

	return ret;
}
Exemplo n.º 15
0
void AnimationTreePlayer::_update_sources() {

	if (master==NodePath())
		return;
	if (!is_inside_tree())
		return;

	Node *m = get_node(master);
	if (!m) {
		master=NodePath();
		ERR_FAIL_COND(!m);
	}

	AnimationPlayer *ap = m->cast_to<AnimationPlayer>();

	if (!ap) {

		master=NodePath();
		ERR_FAIL_COND(!ap);
	}

	for (Map<StringName,NodeBase*>::Element *E=node_map.front();E;E=E->next()) {

		if (E->get()->type==NODE_ANIMATION) {

			AnimationNode *an = static_cast<AnimationNode*>(E->get());

			if (an->from!="") {

				an->animation = ap->get_animation(an->from);
			}
		}
	}


}
void CompositorAnimations::cancelAnimationOnCompositor(const Element& element, const AnimationPlayer& player, int id)
{
    if (!canStartAnimationOnCompositor(element)) {
        // When an element is being detached, we cancel any associated
        // AnimationPlayers for CSS animations. But by the time we get
        // here the mapping will have been removed.
        // FIXME: Defer remove/pause operations until after the
        // compositing update.
        return;
    }
    if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) {
        WebCompositorAnimationPlayer* compositorPlayer = player.compositorPlayer();
        ASSERT(compositorPlayer);
        compositorPlayer->removeAnimation(id);
    } else {
        toLayoutBoxModelObject(element.layoutObject())->layer()->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer()->removeAnimation(id);
    }
}
void CompositorAnimations::pauseAnimationForTestingOnCompositor(const Element& element, const AnimationPlayer& player, int id, double pauseTime)
{
    // FIXME: canStartAnimationOnCompositor queries compositingState, which is not necessarily up to date.
    // https://code.google.com/p/chromium/issues/detail?id=339847
    DisableCompositingQueryAsserts disabler;

    if (!canStartAnimationOnCompositor(element)) {
        ASSERT_NOT_REACHED();
        return;
    }
    if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) {
        WebCompositorAnimationPlayer* compositorPlayer = player.compositorPlayer();
        ASSERT(compositorPlayer);
        compositorPlayer->pauseAnimation(id, pauseTime);
    } else {
        toLayoutBoxModelObject(element.layoutObject())->layer()->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer()->pauseAnimation(id, pauseTime);
    }
}
bool CompositorAnimations::canAttachCompositedLayers(const Element& element, const AnimationPlayer& player)
{
    if (!RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled())
        return false;

    if (!player.compositorPlayer())
        return false;

    if (!element.layoutObject() || !element.layoutObject()->isBoxModelObject())
        return false;

    DeprecatedPaintLayer* layer = toLayoutBoxModelObject(element.layoutObject())->layer();

    if (!layer || !layer->isAllowedToQueryCompositingState()
        || !layer->compositedDeprecatedPaintLayerMapping()
        || !layer->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer())
        return false;

    if (!layer->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer()->platformLayer())
        return false;

    return true;
}
Exemplo n.º 19
0
void AnimController::freeze() {
    if (!_freezing) {
        _freezing = true;
        status_cache.clear();
        for (Map<StringName, Node*>::Element *E = anim_nodes.front(); E; E=E->next()) {
            AnimationPlayer *player = E->get()->cast_to<AnimationPlayer>();
            if (player->is_playing()) {
                AnimationStatus status;
                status.name = player->get_current_animation();
                status.position = player->get_current_animation_pos();
                status.player = player;
                status_cache.push_back(status);
                player->stop(false);
                player->set_active(false);
            }
        }
    }
}
void AnimationNodeBlendTreeEditor::_update_graph() {

	if (updating)
		return;

	graph->set_scroll_ofs(blend_tree->get_graph_offset() * EDSCALE);

	if (blend_tree->get_parent().is_valid()) {
		goto_parent->show();
	} else {
		goto_parent->hide();
	}
	graph->clear_connections();
	//erase all nodes
	for (int i = 0; i < graph->get_child_count(); i++) {

		if (Object::cast_to<GraphNode>(graph->get_child(i))) {
			memdelete(graph->get_child(i));
			i--;
		}
	}

	animations.clear();

	List<StringName> nodes;
	blend_tree->get_node_list(&nodes);

	for (List<StringName>::Element *E = nodes.front(); E; E = E->next()) {

		GraphNode *node = memnew(GraphNode);
		graph->add_child(node);

		Ref<AnimationNode> agnode = blend_tree->get_node(E->get());

		if (!agnode->is_connected("changed", this, "_node_changed")) {
			agnode->connect("changed", this, "_node_changed", varray(agnode->get_instance_id()), CONNECT_DEFERRED);
		}

		node->set_offset(agnode->get_position() * EDSCALE);

		node->set_title(agnode->get_caption());
		node->set_name(E->get());

		int base = 0;
		if (String(E->get()) != "output") {
			LineEdit *name = memnew(LineEdit);
			name->set_text(E->get());
			name->set_expand_to_text_length(true);
			node->add_child(name);
			node->set_slot(0, false, 0, Color(), true, 0, get_color("font_color", "Label"));
			name->connect("text_entered", this, "_node_renamed", varray(agnode));
			name->connect("focus_exited", this, "_node_renamed_focus_out", varray(name, agnode));
			base = 1;
			node->set_show_close_button(true);
			node->connect("close_request", this, "_delete_request", varray(E->get()), CONNECT_DEFERRED);
		}

		for (int i = 0; i < agnode->get_input_count(); i++) {
			Label *in_name = memnew(Label);
			node->add_child(in_name);
			in_name->set_text(agnode->get_input_name(i));
			node->set_slot(base + i, true, 0, get_color("font_color", "Label"), false, 0, Color());
		}

		node->connect("dragged", this, "_node_dragged", varray(agnode));

		if (EditorNode::get_singleton()->item_has_editor(agnode.ptr())) {
			node->add_child(memnew(HSeparator));
			Button *open_in_editor = memnew(Button);
			open_in_editor->set_text(TTR("Open Editor"));
			open_in_editor->set_icon(get_icon("Edit", "EditorIcons"));
			node->add_child(open_in_editor);
			open_in_editor->connect("pressed", this, "_open_in_editor", varray(E->get()), CONNECT_DEFERRED);
			open_in_editor->set_h_size_flags(SIZE_SHRINK_CENTER);
		}

		if (agnode->has_filter()) {

			node->add_child(memnew(HSeparator));
			Button *edit_filters = memnew(Button);
			edit_filters->set_text(TTR("Edit Filters"));
			edit_filters->set_icon(get_icon("AnimationFilter", "EditorIcons"));
			node->add_child(edit_filters);
			edit_filters->connect("pressed", this, "_edit_filters", varray(E->get()), CONNECT_DEFERRED);
			edit_filters->set_h_size_flags(SIZE_SHRINK_CENTER);
		}

		Ref<AnimationNodeAnimation> anim = agnode;
		if (anim.is_valid()) {

			MenuButton *mb = memnew(MenuButton);
			mb->set_text(anim->get_animation());
			mb->set_icon(get_icon("Animation", "EditorIcons"));
			Array options;

			node->add_child(memnew(HSeparator));
			node->add_child(mb);

			ProgressBar *pb = memnew(ProgressBar);

			AnimationTree *player = anim->get_tree();
			if (player->has_node(player->get_animation_player())) {
				AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(player->get_node(player->get_animation_player()));
				if (ap) {
					List<StringName> anims;
					ap->get_animation_list(&anims);

					for (List<StringName>::Element *F = anims.front(); F; F = F->next()) {
						mb->get_popup()->add_item(F->get());
						options.push_back(F->get());
					}

					if (ap->has_animation(anim->get_animation())) {
						pb->set_max(ap->get_animation(anim->get_animation())->get_length());
					}
				}
			}

			pb->set_percent_visible(false);
			animations[E->get()] = pb;
			node->add_child(pb);

			mb->get_popup()->connect("index_pressed", this, "_anim_selected", varray(options, E->get()), CONNECT_DEFERRED);
		}

		Ref<AnimationNodeOneShot> oneshot = agnode;
		if (oneshot.is_valid()) {

			HBoxContainer *play_stop = memnew(HBoxContainer);
			play_stop->add_spacer();
			Button *play = memnew(Button);
			play->set_icon(get_icon("Play", "EditorIcons"));
			play->connect("pressed", this, "_oneshot_start", varray(E->get()), CONNECT_DEFERRED);
			play_stop->add_child(play);
			Button *stop = memnew(Button);
			stop->set_icon(get_icon("Stop", "EditorIcons"));
			stop->connect("pressed", this, "_oneshot_stop", varray(E->get()), CONNECT_DEFERRED);
			play_stop->add_child(stop);
			play_stop->add_spacer();
			node->add_child(play_stop);
		}
	}

	List<AnimationNodeBlendTree::NodeConnection> connections;
	blend_tree->get_node_connections(&connections);

	for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = connections.front(); E; E = E->next()) {

		StringName from = E->get().output_node;
		StringName to = E->get().input_node;
		int to_idx = E->get().input_index;

		graph->connect_node(from, 0, to, to_idx);
	}
}
Exemplo n.º 21
0
Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Set<Ref<ImageTexture> >& image_map) {

	// children first..
	for(int i=0;i<p_node->get_child_count();i++) {


		Node *r = _fix_node(p_node->get_child(i),p_root,collision_map,p_flags,image_map);
		if (!r) {
			print_line("was erased..");
			i--; //was erased
		}
	}

	String name = p_node->get_name();

	bool isroot = p_node==p_root;


	if (!isroot && p_flags&SCENE_FLAG_REMOVE_NOIMP && _teststr(name,"noimp")) {

		memdelete(p_node);
		return NULL;
	}

	{

		List<PropertyInfo> pl;
		p_node->get_property_list(&pl);
		for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {

			if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) {
				_find_resources(p_node->get(E->get().name),image_map);
			}
		}

	}




	if (p_flags&SCENE_FLAG_CREATE_BILLBOARDS && p_node->cast_to<MeshInstance>()) {

		MeshInstance *mi = p_node->cast_to<MeshInstance>();

		bool bb=false;

		if ((_teststr(name,"bb"))) {
			bb=true;
		} else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"bb"))) {
			bb=true;

		}

		if (bb) {
			mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
			if (mi->get_mesh().is_valid()) {

				Ref<Mesh> m = mi->get_mesh();
				for(int i=0;i<m->get_surface_count();i++) {

					Ref<FixedMaterial> fm = m->surface_get_material(i);
					if (fm.is_valid()) {
						fm->set_flag(Material::FLAG_UNSHADED,true);
						fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
						fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
						fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
					}
				}
			}
		}
	}

	if (p_flags&SCENE_FLAG_REMOVE_NOIMP && p_node->cast_to<AnimationPlayer>()) {
		//remove animations referencing non-importable nodes
		AnimationPlayer *ap = p_node->cast_to<AnimationPlayer>();

		List<StringName> anims;
		ap->get_animation_list(&anims);
		for(List<StringName>::Element *E=anims.front();E;E=E->next()) {

			Ref<Animation> anim=ap->get_animation(E->get());
			ERR_CONTINUE(anim.is_null());
			for(int i=0;i<anim->get_track_count();i++) {
				NodePath path = anim->track_get_path(i);

				for(int j=0;j<path.get_name_count();j++) {
					String node = path.get_name(j);
					if (_teststr(node,"noimp")) {
						anim->remove_track(i);
						i--;
						break;
					}
				}
			}

		}
	}


	if (p_flags&SCENE_FLAG_CREATE_IMPOSTORS && p_node->cast_to<MeshInstance>()) {

		MeshInstance *mi = p_node->cast_to<MeshInstance>();

		String str;

		if ((_teststr(name,"imp"))) {
			str=name;
		} else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"imp"))) {
			str=mi->get_mesh()->get_name();

		}


		if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
			MeshInstance *mi = p_node->cast_to<MeshInstance>();
			MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
			String d=str.substr(str.find("imp")+3,str.length());
			if (d!="") {
				if ((d[0]<'0' || d[0]>'9'))
					d=d.substr(1,d.length());
				if (d.length() && d[0]>='0' && d[0]<='9') {
					float dist = d.to_double();
					mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
					mi->set_flag(GeometryInstance::FLAG_BILLBOARD_FIX_Y,true);
					mi->set_draw_range_begin(dist);
					mi->set_draw_range_end(100000);

					mip->set_draw_range_begin(0);
					mip->set_draw_range_end(dist);

					if (mi->get_mesh().is_valid()) {

						Ref<Mesh> m = mi->get_mesh();
						for(int i=0;i<m->get_surface_count();i++) {

							Ref<FixedMaterial> fm = m->surface_get_material(i);
							if (fm.is_valid()) {
								fm->set_flag(Material::FLAG_UNSHADED,true);
								fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
								fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
								fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
							}
						}
					}
				}
			}
		}
	}

    if (p_flags&SCENE_FLAG_CREATE_LODS && p_node->cast_to<MeshInstance>()) {

	MeshInstance *mi = p_node->cast_to<MeshInstance>();

	String str;

	if ((_teststr(name,"lod"))) {
	    str=name;
	} else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"lod"))) {
	    str=mi->get_mesh()->get_name();

	}


	if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
	    MeshInstance *mi = p_node->cast_to<MeshInstance>();
	    MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
	    String d=str.substr(str.find("lod")+3,str.length());
	    if (d!="") {
		if ((d[0]<'0' || d[0]>'9'))
		    d=d.substr(1,d.length());
		if (d.length() && d[0]>='0' && d[0]<='9') {
		    float dist = d.to_double();
		    mi->set_draw_range_begin(dist);
		    mi->set_draw_range_end(100000);

		    mip->set_draw_range_begin(0);
		    mip->set_draw_range_end(dist);

		    /*if (mi->get_mesh().is_valid()) {

			Ref<Mesh> m = mi->get_mesh();
			for(int i=0;i<m->get_surface_count();i++) {

			    Ref<FixedMaterial> fm = m->surface_get_material(i);
			    if (fm.is_valid()) {
				fm->set_flag(Material::FLAG_UNSHADED,true);
				fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
				fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
				fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
			    }
			}
		    }*/
		}
	    }
	}
    }
	if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly") && p_node->cast_to<MeshInstance>()) {

		if (isroot)
			return p_node;

		MeshInstance *mi = p_node->cast_to<MeshInstance>();
		Node * col = mi->create_trimesh_collision_node();

		ERR_FAIL_COND_V(!col,NULL);
		col->set_name(_fixstr(name,"colonly"));
		col->cast_to<Spatial>()->set_transform(mi->get_transform());
		p_node->replace_by(col);
		memdelete(p_node);
		p_node=col;

	} else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS &&_teststr(name,"col") && p_node->cast_to<MeshInstance>()) {


		MeshInstance *mi = p_node->cast_to<MeshInstance>();

		mi->set_name(_fixstr(name,"col"));
		mi->create_trimesh_collision();
	} else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to<MeshInstance>()) {


		if (isroot)
			return p_node;

		MeshInstance *mi = p_node->cast_to<MeshInstance>();
		DVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);


		BSP_Tree bsptree(faces);

		Ref<RoomBounds> area = memnew( RoomBounds );
		area->set_bounds(faces);
		area->set_geometry_hint(faces);


		Room * room = memnew( Room );
		room->set_name(_fixstr(name,"room"));
		room->set_transform(mi->get_transform());
		room->set_room(area);

		p_node->replace_by(room);
		memdelete(p_node);
		p_node=room;

	} else if (p_flags&SCENE_FLAG_CREATE_ROOMS &&_teststr(name,"room")) {

		if (isroot)
			return p_node;

		Spatial *dummy = p_node->cast_to<Spatial>();
		ERR_FAIL_COND_V(!dummy,NULL);

		Room * room = memnew( Room );
		room->set_name(_fixstr(name,"room"));
		room->set_transform(dummy->get_transform());

		p_node->replace_by(room);
		memdelete(p_node);
		p_node=room;

		room->compute_room_from_subtree();

	} else if (p_flags&SCENE_FLAG_CREATE_PORTALS &&_teststr(name,"portal") && p_node->cast_to<MeshInstance>()) {

		if (isroot)
			return p_node;

		MeshInstance *mi = p_node->cast_to<MeshInstance>();
		DVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);

		ERR_FAIL_COND_V(faces.size()==0,NULL);
		//step 1 compute the plane
		Set<Vector3> points;
		Plane plane;

		Vector3 center;

		for(int i=0;i<faces.size();i++) {

			Face3 f = faces.get(i);
			Plane p = f.get_plane();
			plane.normal+=p.normal;
			plane.d+=p.d;

			for(int i=0;i<3;i++) {

				Vector3 v = f.vertex[i].snapped(0.01);
				if (!points.has(v)) {
					points.insert(v);
					center+=v;
				}
			}
		}

		plane.normal.normalize();
		plane.d/=faces.size();
		center/=points.size();

		//step 2, create points

		Transform t;
		t.basis.from_z(plane.normal);
		t.basis.transpose();
		t.origin=center;

		Vector<Point2> portal_points;

		for(Set<Vector3>::Element *E=points.front();E;E=E->next()) {

			Vector3 local = t.xform_inv(E->get());
			portal_points.push_back(Point2(local.x,local.y));
		}
		// step 3 bubbly sort points

		int swaps=0;

		do {
			swaps=0;

			for(int i=0;i<portal_points.size()-1;i++) {

				float a = portal_points[i].atan2();
				float b = portal_points[i+1].atan2();

				if (a>b) {
					SWAP( portal_points[i], portal_points[i+1] );
					swaps++;
				}

			}

		} while(swaps);


		Portal *portal = memnew( Portal );

		portal->set_shape(portal_points);
		portal->set_transform( mi->get_transform() * t);

		p_node->replace_by(portal);
		memdelete(p_node);
		p_node=portal;

	} else if (p_node->cast_to<MeshInstance>()) {

		//last attempt, maybe collision insde the mesh data

		MeshInstance *mi = p_node->cast_to<MeshInstance>();

		Ref<Mesh> mesh = mi->get_mesh();
		if (!mesh.is_null()) {

			if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(mesh->get_name(),"col")) {

				mesh->set_name( _fixstr(mesh->get_name(),"col") );
				Ref<Shape> shape;

				if (collision_map.has(mesh)) {
					shape = collision_map[mesh];

				} else {

					shape = mesh->create_trimesh_shape();
					if (!shape.is_null())
						collision_map[mesh]=shape;


				}

				if (!shape.is_null()) {
#if 0
					StaticBody* static_body = memnew( StaticBody );
					ERR_FAIL_COND_V(!static_body,NULL);
					static_body->set_name( String(mesh->get_name()) + "_col" );
					shape->set_name(static_body->get_name());
					static_body->add_shape(shape);

					mi->add_child(static_body);
					if (mi->get_owner())
						static_body->set_owner( mi->get_owner() );
#endif
				}

			}

			for(int i=0;i<mesh->get_surface_count();i++) {

				Ref<FixedMaterial> fm = mesh->surface_get_material(i);
				if (fm.is_valid()) {
					String name = fm->get_name();
					if (_teststr(name,"alpha")) {
						fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
						name=_fixstr(name,"alpha");
					}

					if (_teststr(name,"vcol")) {
						fm->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true);
						name=_fixstr(name,"vcol");
					}
					fm->set_name(name);
				}
			}

		}

	}




	return p_node;
}
Exemplo n.º 22
0
nsIStyleRule*
nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
                                       mozilla::dom::Element* aElement)
{
  // FIXME (bug 960465): This test should go away.
  if (!mPresContext->RestyleManager()->IsProcessingAnimationStyleChange()) {
    if (!mPresContext->IsDynamic()) {
      // For print or print preview, ignore animations.
      return nullptr;
    }

    // Everything that causes our animation data to change triggers a
    // style change, which in turn triggers a non-animation restyle.
    // Likewise, when we initially construct frames, we're not in a
    // style change, but also not in an animation restyle.

    const nsStyleDisplay* disp = aStyleContext->StyleDisplay();
    AnimationPlayerCollection* collection =
      GetAnimationPlayers(aElement, aStyleContext->GetPseudoType(), false);
    if (!collection &&
        disp->mAnimationNameCount == 1 &&
        disp->mAnimations[0].GetName().IsEmpty()) {
      return nullptr;
    }

    // build the animations list
    dom::AnimationTimeline* timeline = aElement->OwnerDoc()->Timeline();
    AnimationPlayerPtrArray newPlayers;
    BuildAnimations(aStyleContext, aElement, timeline, newPlayers);

    if (newPlayers.IsEmpty()) {
      if (collection) {
        collection->Destroy();
      }
      return nullptr;
    }

    if (collection) {
      collection->mStyleRule = nullptr;
      collection->mStyleRuleRefreshTime = TimeStamp();
      collection->UpdateAnimationGeneration(mPresContext);

      // Copy over the start times and (if still paused) pause starts
      // for each animation (matching on name only) that was also in the
      // old list of animations.
      // This means that we honor dynamic changes, which isn't what the
      // spec says to do, but WebKit seems to honor at least some of
      // them.  See
      // http://lists.w3.org/Archives/Public/www-style/2011Apr/0079.html
      // In order to honor what the spec said, we'd copy more data over
      // (or potentially optimize BuildAnimations to avoid rebuilding it
      // in the first place).
      if (!collection->mPlayers.IsEmpty()) {

        for (size_t newIdx = newPlayers.Length(); newIdx-- != 0;) {
          AnimationPlayer* newPlayer = newPlayers[newIdx];

          // Find the matching animation with this name in the old list
          // of animations.  We iterate through both lists in a backwards
          // direction which means that if there are more animations in
          // the new list of animations with a given name than in the old
          // list, it will be the animations towards the of the beginning of
          // the list that do not match and are treated as new animations.
          nsRefPtr<CSSAnimationPlayer> oldPlayer;
          size_t oldIdx = collection->mPlayers.Length();
          while (oldIdx-- != 0) {
            CSSAnimationPlayer* a =
              collection->mPlayers[oldIdx]->AsCSSAnimationPlayer();
            MOZ_ASSERT(a, "All players in the CSS Animation collection should"
                          " be CSSAnimationPlayer objects");
            if (a->Name() == newPlayer->Name()) {
              oldPlayer = a;
              break;
            }
          }
          if (!oldPlayer) {
            continue;
          }

          // Update the old from the new so we can keep the original object
          // identity (and any expando properties attached to it).
          if (oldPlayer->GetSource() && newPlayer->GetSource()) {
            Animation* oldAnim = oldPlayer->GetSource();
            Animation* newAnim = newPlayer->GetSource();
            oldAnim->Timing() = newAnim->Timing();
            oldAnim->Properties() = newAnim->Properties();
          }

          // Reset compositor state so animation will be re-synchronized.
          oldPlayer->ClearIsRunningOnCompositor();

          // Handle changes in play state.
          // CSSAnimationPlayer takes care of override behavior so that,
          // for example, if the author has called pause(), that will
          // override the animation-play-state.
          // (We should check newPlayer->IsStylePaused() but that requires
          //  downcasting to CSSAnimationPlayer and we happen to know that
          //  newPlayer will only ever be paused by calling PauseFromStyle
          //  making IsPaused synonymous in this case.)
          if (!oldPlayer->IsStylePaused() && newPlayer->IsPaused()) {
            oldPlayer->PauseFromStyle();
          } else if (oldPlayer->IsStylePaused() && !newPlayer->IsPaused()) {
            oldPlayer->PlayFromStyle();
          }

          // Replace new animation with the (updated) old one and remove the
          // old one from the array so we don't try to match it any more.
          //
          // Although we're doing this while iterating this is safe because
          // we're not changing the length of newPlayers and we've finished
          // iterating over the list of old iterations.
          newPlayer = nullptr;
          newPlayers.ReplaceElementAt(newIdx, oldPlayer);
          collection->mPlayers.RemoveElementAt(oldIdx);
        }
      }
    } else {
      collection =
        GetAnimationPlayers(aElement, aStyleContext->GetPseudoType(), true);
    }
    collection->mPlayers.SwapElements(newPlayers);
    collection->mNeedsRefreshes = true;
    collection->Tick();

    TimeStamp refreshTime = mPresContext->RefreshDriver()->MostRecentRefresh();
    UpdateStyleAndEvents(collection, refreshTime,
                         EnsureStyleRule_IsNotThrottled);
    // We don't actually dispatch the mPendingEvents now.  We'll either
    // dispatch them the next time we get a refresh driver notification
    // or the next time somebody calls
    // nsPresShell::FlushPendingNotifications.
    if (!mPendingEvents.IsEmpty()) {
      mPresContext->Document()->SetNeedStyleFlush();
    }
  }

  return GetAnimationRule(aElement, aStyleContext->GetPseudoType());
}
Exemplo n.º 23
0
void CSSAnimations::maybeApplyPendingUpdate(Element* element)
{
    if (!m_pendingUpdate) {
        m_previousActiveInterpolationsForAnimations.clear();
        return;
    }

    OwnPtr<CSSAnimationUpdate> update = m_pendingUpdate.release();

    m_previousActiveInterpolationsForAnimations.swap(update->activeInterpolationsForAnimations());

    for (Vector<AtomicString>::const_iterator iter = update->cancelledAnimationNames().begin(); iter != update->cancelledAnimationNames().end(); ++iter) {
        RefPtr<AnimationPlayer> player = m_animations.take(*iter);
        player->cancel();
        player->update(TimingUpdateOnDemand);
    }

    for (Vector<AtomicString>::const_iterator iter = update->animationsWithPauseToggled().begin(); iter != update->animationsWithPauseToggled().end(); ++iter) {
        AnimationPlayer* player = m_animations.get(*iter);
        if (player->paused())
            player->unpause();
        else
            player->pause();
        if (player->outdated())
            player->update(TimingUpdateOnDemand);
    }

    for (Vector<CSSAnimationUpdate::NewAnimation>::const_iterator iter = update->newAnimations().begin(); iter != update->newAnimations().end(); ++iter) {
        const InertAnimation* inertAnimation = iter->animation.get();
        OwnPtr<AnimationEventDelegate> eventDelegate = adoptPtr(new AnimationEventDelegate(element, iter->name));
        RefPtr<Animation> animation = Animation::create(element, inertAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPriority, eventDelegate.release());
        RefPtr<AnimationPlayer> player = element->document().timeline().createAnimationPlayer(animation.get());
        if (inertAnimation->paused())
            player->pause();
        player->update(TimingUpdateOnDemand);
        m_animations.set(iter->name, player.get());
    }

    // Transitions that are run on the compositor only update main-thread state
    // lazily. However, we need the new state to know what the from state shoud
    // be when transitions are retargeted. Instead of triggering complete style
    // recalculation, we find these cases by searching for new transitions that
    // have matching cancelled animation property IDs on the compositor.
    HashMap<CSSPropertyID, std::pair<RefPtr<Animation>, double> > retargetedCompositorTransitions;
    for (HashSet<CSSPropertyID>::iterator iter = update->cancelledTransitions().begin(); iter != update->cancelledTransitions().end(); ++iter) {
        CSSPropertyID id = *iter;
        ASSERT(m_transitions.contains(id));

        RefPtr<AnimationPlayer> player = m_transitions.take(id).player;
        player->cancel();
        player->update(TimingUpdateOnDemand);
    }

    for (CSSAnimationUpdate::NewTransitionMap::const_iterator iter = update->newTransitions().begin(); iter != update->newTransitions().end(); ++iter) {
        const CSSAnimationUpdate::NewTransition& newTransition = iter->value;

        RunningTransition runningTransition;
        runningTransition.from = newTransition.from;
        runningTransition.to = newTransition.to;

        CSSPropertyID id = newTransition.id;
        InertAnimation* inertAnimation = newTransition.animation.get();
        OwnPtr<TransitionEventDelegate> eventDelegate = adoptPtr(new TransitionEventDelegate(element, newTransition.eventId));

        RefPtr<AnimationEffect> effect = inertAnimation->effect();
        RefPtr<Animation> transition = Animation::create(element, effect, inertAnimation->specifiedTiming(), Animation::TransitionPriority, eventDelegate.release());
        RefPtr<AnimationPlayer> player = element->document().timeline().createAnimationPlayer(transition.get());
        player->update(TimingUpdateOnDemand);
        runningTransition.player = player;
        m_transitions.set(id, runningTransition);
        ASSERT(id != CSSPropertyInvalid);
    }
}
Exemplo n.º 24
0
void CSSAnimations::maybeApplyPendingUpdate(Element* element)
{
    if (!m_pendingUpdate) {
        m_previousActiveInterpolationsForAnimations.clear();
        return;
    }

    OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = m_pendingUpdate.release();

    m_previousActiveInterpolationsForAnimations.swap(update->activeInterpolationsForAnimations());

    // FIXME: cancelling, pausing, unpausing animations all query compositingState, which is not necessarily up to date here
    // since we call this from recalc style.
    // https://code.google.com/p/chromium/issues/detail?id=339847
    DisableCompositingQueryAsserts disabler;

    for (const AtomicString& animationName : update->cancelledAnimationNames()) {
        RefPtrWillBeRawPtr<AnimationPlayer> player = m_animations.take(animationName);
        player->cancel();
        player->update(TimingUpdateOnDemand);
    }

    for (const AtomicString& animationName : update->animationsWithPauseToggled()) {
        AnimationPlayer* player = m_animations.get(animationName);
        if (player->paused())
            player->unpause();
        else
            player->pause();
        if (player->outdated())
            player->update(TimingUpdateOnDemand);
    }

    for (const auto& entry : update->newAnimations()) {
        const InertAnimation* inertAnimation = entry.animation.get();
        OwnPtrWillBeRawPtr<AnimationEventDelegate> eventDelegate = adoptPtrWillBeNoop(new AnimationEventDelegate(element, entry.name));
        RefPtrWillBeRawPtr<Animation> animation = Animation::create(element, inertAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPriority, eventDelegate.release());
        animation->setName(inertAnimation->name());
        RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timeline().createAnimationPlayer(animation.get());
        if (inertAnimation->paused())
            player->pause();
        player->update(TimingUpdateOnDemand);
        m_animations.set(entry.name, player.get());
    }

    // Transitions that are run on the compositor only update main-thread state
    // lazily. However, we need the new state to know what the from state shoud
    // be when transitions are retargeted. Instead of triggering complete style
    // recalculation, we find these cases by searching for new transitions that
    // have matching cancelled animation property IDs on the compositor.
    WillBeHeapHashMap<CSSPropertyID, std::pair<RefPtrWillBeMember<Animation>, double>> retargetedCompositorTransitions;
    for (CSSPropertyID id : update->cancelledTransitions()) {
        ASSERT(m_transitions.contains(id));

        RefPtrWillBeRawPtr<AnimationPlayer> player = m_transitions.take(id).player;
        Animation* animation = toAnimation(player->source());
        if (animation->hasActiveAnimationsOnCompositor(id) && update->newTransitions().find(id) != update->newTransitions().end())
            retargetedCompositorTransitions.add(id, std::pair<RefPtrWillBeMember<Animation>, double>(animation, player->startTimeInternal()));
        player->cancel();
        player->update(TimingUpdateOnDemand);
    }

    for (const auto& entry : update->newTransitions()) {
        const CSSAnimationUpdate::NewTransition& newTransition = entry.value;

        RunningTransition runningTransition;
        runningTransition.from = newTransition.from;
        runningTransition.to = newTransition.to;

        CSSPropertyID id = newTransition.id;
        InertAnimation* inertAnimation = newTransition.animation.get();
        OwnPtrWillBeRawPtr<TransitionEventDelegate> eventDelegate = adoptPtrWillBeNoop(new TransitionEventDelegate(element, newTransition.eventId));

        RefPtrWillBeRawPtr<AnimationEffect> effect = inertAnimation->effect();

        if (retargetedCompositorTransitions.contains(id)) {
            const std::pair<RefPtrWillBeMember<Animation>, double>& oldTransition = retargetedCompositorTransitions.get(id);
            RefPtrWillBeRawPtr<Animation> oldAnimation = oldTransition.first;
            double oldStartTime = oldTransition.second;
            double inheritedTime = isNull(oldStartTime) ? 0 : element->document().timeline().currentTimeInternal() - oldStartTime;

            AnimatableValueKeyframeEffectModel* oldEffect = toAnimatableValueKeyframeEffectModel(inertAnimation->effect());
            const KeyframeVector& frames = oldEffect->getFrames();

            AnimatableValueKeyframeVector newFrames;
            newFrames.append(toAnimatableValueKeyframe(frames[0]->clone().get()));
            newFrames.append(toAnimatableValueKeyframe(frames[1]->clone().get()));

            newFrames[0]->clearPropertyValue(id);
            RefPtrWillBeRawPtr<InertAnimation> inertAnimationForSampling = InertAnimation::create(oldAnimation->effect(), oldAnimation->specifiedTiming(), false);
            OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation>>> sample = inertAnimationForSampling->sample(inheritedTime);
            ASSERT(sample->size() == 1);
            newFrames[0]->setPropertyValue(id, toLegacyStyleInterpolation(sample->at(0).get())->currentValue());

            effect = AnimatableValueKeyframeEffectModel::create(newFrames);
        }

        RefPtrWillBeRawPtr<Animation> transition = Animation::create(element, effect, inertAnimation->specifiedTiming(), Animation::TransitionPriority, eventDelegate.release());
        transition->setName(inertAnimation->name());
        RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timeline().createAnimationPlayer(transition.get());
        player->update(TimingUpdateOnDemand);
        runningTransition.player = player;
        m_transitions.set(id, runningTransition);
        ASSERT(id != CSSPropertyInvalid);
        blink::Platform::current()->histogramSparse("WebCore.Animation.CSSProperties", UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(id));
    }
}
Exemplo n.º 25
0
void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const Element* animatingElement, Element& element, const RenderStyle& style, RenderStyle* parentStyle, StyleResolver* resolver)
{
    const ActiveAnimations* activeAnimations = animatingElement ? animatingElement->activeAnimations() : nullptr;

#if !ENABLE(ASSERT)
    // If we're in an animation style change, no animations can have started, been cancelled or changed play state.
    // When ASSERT is enabled, we verify this optimization.
    if (activeAnimations && activeAnimations->isAnimationStyleChange())
        return;
#endif

    const CSSAnimationData* animationData = style.animations();
    const CSSAnimations* cssAnimations = activeAnimations ? &activeAnimations->cssAnimations() : nullptr;

    HashSet<AtomicString> inactive;
    if (cssAnimations) {
        for (const auto& entry : cssAnimations->m_animations)
            inactive.add(entry.key);
    }

    if (style.display() != NONE) {
        for (size_t i = 0; animationData && i < animationData->nameList().size(); ++i) {
            AtomicString animationName(animationData->nameList()[i]);
            if (animationName == CSSAnimationData::initialName())
                continue;

            bool isPaused = CSSTimingData::getRepeated(animationData->playStateList(), i) == AnimPlayStatePaused;

            // Keyframes and animation properties are snapshotted when the
            // animation starts, so we don't need to track changes to these,
            // with the exception of play-state.
            if (cssAnimations) {
                AnimationMap::const_iterator existing(cssAnimations->m_animations.find(animationName));
                if (existing != cssAnimations->m_animations.end()) {
                    inactive.remove(animationName);
                    AnimationPlayer* player = existing->value.get();
                    if (isPaused != player->paused()) {
                        ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange());
                        update->toggleAnimationPaused(animationName);
                    }
                    continue;
                }
            }

            Timing timing = animationData->convertToTiming(i);
            RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunction;
            timing.timingFunction = Timing::defaults().timingFunction;
            AnimatableValueKeyframeVector resolvedKeyframes;
            resolveKeyframes(resolver, animatingElement, element, style, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes);
            if (!resolvedKeyframes.isEmpty()) {
                ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange());
                update->startAnimation(animationName, InertAnimation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused));
            }
        }
    }

    ASSERT(inactive.isEmpty() || cssAnimations);
    for (const AtomicString& animationName : inactive) {
        ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange());
        update->cancelAnimation(animationName, *cssAnimations->m_animations.get(animationName));
    }
}
Exemplo n.º 26
0
void AnimationTree::_process_graph(float p_delta) {

	_update_properties(); //if properties need updating, update them

	//check all tracks, see if they need modification

	root_motion_transform = Transform();

	if (!root.is_valid()) {
		ERR_PRINT("AnimationTree: root AnimationNode is not set, disabling playback.");
		set_active(false);
		cache_valid = false;
		return;
	}

	if (!has_node(animation_player)) {
		ERR_PRINT("AnimationTree: no valid AnimationPlayer path set, disabling playback");
		set_active(false);
		cache_valid = false;
		return;
	}

	AnimationPlayer *player = Object::cast_to<AnimationPlayer>(get_node(animation_player));

	ObjectID current_animation_player = 0;

	if (player) {
		current_animation_player = player->get_instance_id();
	}

	if (last_animation_player != current_animation_player) {

		if (last_animation_player) {
			Object *old_player = ObjectDB::get_instance(last_animation_player);
			if (old_player) {
				old_player->disconnect("caches_cleared", this, "_clear_caches");
			}
		}

		if (player) {
			player->connect("caches_cleared", this, "_clear_caches");
		}

		last_animation_player = current_animation_player;
	}

	if (!player) {
		ERR_PRINT("AnimationTree: path points to a node not an AnimationPlayer, disabling playback");
		set_active(false);
		cache_valid = false;
		return;
	}

	if (!cache_valid) {
		if (!_update_caches(player)) {
			return;
		}
	}

	{ //setup

		process_pass++;

		state.valid = true;
		state.invalid_reasons = "";
		state.animation_states.clear(); //will need to be re-created
		state.valid = true;
		state.player = player;
		state.last_pass = process_pass;
		state.tree = this;

		// root source blends

		root->blends.resize(state.track_count);
		float *src_blendsw = root->blends.ptrw();
		for (int i = 0; i < state.track_count; i++) {
			src_blendsw[i] = 1.0; //by default all go to 1 for the root input
		}
	}

	//process

	{

		if (started) {
			//if started, seek
			root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path, NULL, &state, 0, true, Vector<StringName>());
			started = false;
		}

		root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path, NULL, &state, p_delta, false, Vector<StringName>());
	}

	if (!state.valid) {
		return; //state is not valid. do nothing.
	}
	//apply value/transform/bezier blends to track caches and execute method/audio/animation tracks

	{

		bool can_call = is_inside_tree() && !Engine::get_singleton()->is_editor_hint();

		for (List<AnimationNode::AnimationState>::Element *E = state.animation_states.front(); E; E = E->next()) {

			const AnimationNode::AnimationState &as = E->get();

			Ref<Animation> a = as.animation;
			float time = as.time;
			float delta = as.delta;
			bool seeked = as.seeked;

			for (int i = 0; i < a->get_track_count(); i++) {

				NodePath path = a->track_get_path(i);

				ERR_CONTINUE(!track_cache.has(path));

				TrackCache *track = track_cache[path];
				if (track->type != a->track_get_type(i)) {
					continue; //may happen should not
				}

				track->root_motion = root_motion_track == path;

				ERR_CONTINUE(!state.track_map.has(path));
				int blend_idx = state.track_map[path];

				ERR_CONTINUE(blend_idx < 0 || blend_idx >= state.track_count);

				float blend = (*as.track_blends)[blend_idx];

				if (blend < CMP_EPSILON)
					continue; //nothing to blend

				switch (track->type) {

					case Animation::TYPE_TRANSFORM: {

						TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);

						if (track->root_motion) {

							if (t->process_pass != process_pass) {

								t->process_pass = process_pass;
								t->loc = Vector3();
								t->rot = Quat();
								t->rot_blend_accum = 0;
								t->scale = Vector3(1, 1, 1);
							}

							float prev_time = time - delta;
							if (prev_time < 0) {
								if (!a->has_loop()) {
									prev_time = 0;
								} else {
									prev_time = a->get_length() + prev_time;
								}
							}

							Vector3 loc[2];
							Quat rot[2];
							Vector3 scale[2];

							if (prev_time > time) {

								Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
								if (err != OK) {
									continue;
								}

								a->transform_track_interpolate(i, a->get_length(), &loc[1], &rot[1], &scale[1]);

								t->loc += (loc[1] - loc[0]) * blend;
								t->scale += (scale[1] - scale[0]) * blend;
								Quat q = Quat().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
								t->rot = (t->rot * q).normalized();

								prev_time = 0;
							}

							Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
							if (err != OK) {
								continue;
							}

							a->transform_track_interpolate(i, time, &loc[1], &rot[1], &scale[1]);

							t->loc += (loc[1] - loc[0]) * blend;
							t->scale += (scale[1] - scale[0]) * blend;
							Quat q = Quat().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
							t->rot = (t->rot * q).normalized();

							prev_time = 0;

						} else {
							Vector3 loc;
							Quat rot;
							Vector3 scale;

							Error err = a->transform_track_interpolate(i, time, &loc, &rot, &scale);
							//ERR_CONTINUE(err!=OK); //used for testing, should be removed

							if (t->process_pass != process_pass) {

								t->process_pass = process_pass;
								t->loc = loc;
								t->rot = rot;
								t->rot_blend_accum = 0;
								t->scale = scale;
							}

							if (err != OK)
								continue;

							t->loc = t->loc.linear_interpolate(loc, blend);
							if (t->rot_blend_accum == 0) {
								t->rot = rot;
								t->rot_blend_accum = blend;
							} else {
								float rot_total = t->rot_blend_accum + blend;
								t->rot = rot.slerp(t->rot, t->rot_blend_accum / rot_total).normalized();
								t->rot_blend_accum = rot_total;
							}
							t->scale = t->scale.linear_interpolate(scale, blend);
						}

					} break;
					case Animation::TYPE_VALUE: {

						TrackCacheValue *t = static_cast<TrackCacheValue *>(track);

						Animation::UpdateMode update_mode = a->value_track_get_update_mode(i);

						if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) { //delta == 0 means seek

							Variant value = a->value_track_interpolate(i, time);

							if (value == Variant())
								continue;

							if (t->process_pass != process_pass) {
								t->value = value;
								t->process_pass = process_pass;
							}

							Variant::interpolate(t->value, value, blend, t->value);

						} else if (delta != 0) {

							List<int> indices;
							a->value_track_get_key_indices(i, time, delta, &indices);

							for (List<int>::Element *F = indices.front(); F; F = F->next()) {

								Variant value = a->track_get_key_value(i, F->get());
								t->object->set_indexed(t->subpath, value);
							}
						}

					} break;
					case Animation::TYPE_METHOD: {

						if (delta == 0) {
							continue;
						}
						TrackCacheMethod *t = static_cast<TrackCacheMethod *>(track);

						List<int> indices;

						a->method_track_get_key_indices(i, time, delta, &indices);

						for (List<int>::Element *F = indices.front(); F; F = F->next()) {

							StringName method = a->method_track_get_name(i, F->get());
							Vector<Variant> params = a->method_track_get_params(i, F->get());

							int s = params.size();

							ERR_CONTINUE(s > VARIANT_ARG_MAX);
							if (can_call) {
								t->object->call_deferred(
										method,
										s >= 1 ? params[0] : Variant(),
										s >= 2 ? params[1] : Variant(),
										s >= 3 ? params[2] : Variant(),
										s >= 4 ? params[3] : Variant(),
										s >= 5 ? params[4] : Variant());
							}
						}

					} break;
					case Animation::TYPE_BEZIER: {

						TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track);

						float bezier = a->bezier_track_interpolate(i, time);

						if (t->process_pass != process_pass) {
							t->value = bezier;
							t->process_pass = process_pass;
						}

						t->value = Math::lerp(t->value, bezier, blend);

					} break;
					case Animation::TYPE_AUDIO: {

						TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track);

						if (seeked) {
							//find whathever should be playing
							int idx = a->track_find_key(i, time);
							if (idx < 0)
								continue;

							Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
							if (!stream.is_valid()) {
								t->object->call("stop");
								t->playing = false;
								playing_caches.erase(t);
							} else {
								float start_ofs = a->audio_track_get_key_start_offset(i, idx);
								start_ofs += time - a->track_get_key_time(i, idx);
								float end_ofs = a->audio_track_get_key_end_offset(i, idx);
								float len = stream->get_length();

								if (start_ofs > len - end_ofs) {
									t->object->call("stop");
									t->playing = false;
									playing_caches.erase(t);
									continue;
								}

								t->object->call("set_stream", stream);
								t->object->call("play", start_ofs);

								t->playing = true;
								playing_caches.insert(t);
								if (len && end_ofs > 0) { //force a end at a time
									t->len = len - start_ofs - end_ofs;
								} else {
									t->len = 0;
								}

								t->start = time;
							}

						} else {
							//find stuff to play
							List<int> to_play;
							a->track_get_key_indices_in_range(i, time, delta, &to_play);
							if (to_play.size()) {
								int idx = to_play.back()->get();

								Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
								if (!stream.is_valid()) {
									t->object->call("stop");
									t->playing = false;
									playing_caches.erase(t);
								} else {
									float start_ofs = a->audio_track_get_key_start_offset(i, idx);
									float end_ofs = a->audio_track_get_key_end_offset(i, idx);
									float len = stream->get_length();

									t->object->call("set_stream", stream);
									t->object->call("play", start_ofs);

									t->playing = true;
									playing_caches.insert(t);
									if (len && end_ofs > 0) { //force a end at a time
										t->len = len - start_ofs - end_ofs;
									} else {
										t->len = 0;
									}

									t->start = time;
								}
							} else if (t->playing) {

								bool loop = a->has_loop();

								bool stop = false;

								if (!loop && time < t->start) {
									stop = true;
								} else if (t->len > 0) {
									float len = t->start > time ? (a->get_length() - t->start) + time : time - t->start;

									if (len > t->len) {
										stop = true;
									}
								}

								if (stop) {
									//time to stop
									t->object->call("stop");
									t->playing = false;
									playing_caches.erase(t);
								}
							}
						}

						float db = Math::linear2db(MAX(blend, 0.00001));
						if (t->object->has_method("set_unit_db")) {
							t->object->call("set_unit_db", db);
						} else {
							t->object->call("set_volume_db", db);
						}
					} break;
					case Animation::TYPE_ANIMATION: {

						TrackCacheAnimation *t = static_cast<TrackCacheAnimation *>(track);

						AnimationPlayer *player2 = Object::cast_to<AnimationPlayer>(t->object);

						if (!player2)
							continue;

						if (delta == 0 || seeked) {
							//seek
							int idx = a->track_find_key(i, time);
							if (idx < 0)
								continue;

							float pos = a->track_get_key_time(i, idx);

							StringName anim_name = a->animation_track_get_key_animation(i, idx);
							if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name))
								continue;

							Ref<Animation> anim = player2->get_animation(anim_name);

							float at_anim_pos;

							if (anim->has_loop()) {
								at_anim_pos = Math::fposmod(time - pos, anim->get_length()); //seek to loop
							} else {
								at_anim_pos = MAX(anim->get_length(), time - pos); //seek to end
							}

							if (player2->is_playing() || seeked) {
								player2->play(anim_name);
								player2->seek(at_anim_pos);
								t->playing = true;
								playing_caches.insert(t);
							} else {
								player2->set_assigned_animation(anim_name);
								player2->seek(at_anim_pos, true);
							}
						} else {
							//find stuff to play
							List<int> to_play;
							a->track_get_key_indices_in_range(i, time, delta, &to_play);
							if (to_play.size()) {
								int idx = to_play.back()->get();

								StringName anim_name = a->animation_track_get_key_animation(i, idx);
								if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name)) {

									if (playing_caches.has(t)) {
										playing_caches.erase(t);
										player2->stop();
										t->playing = false;
									}
								} else {
									player2->play(anim_name);
									t->playing = true;
									playing_caches.insert(t);
								}
							}
						}

					} break;
				}
			}
		}
	}

	{
		// finally, set the tracks
		const NodePath *K = NULL;
		while ((K = track_cache.next(K))) {
			TrackCache *track = track_cache[*K];
			if (track->process_pass != process_pass)
				continue; //not processed, ignore

			switch (track->type) {

				case Animation::TYPE_TRANSFORM: {

					TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);

					Transform xform;
					xform.origin = t->loc;

					xform.basis.set_quat_scale(t->rot, t->scale);

					if (t->root_motion) {

						root_motion_transform = xform;

						if (t->skeleton && t->bone_idx >= 0) {
							root_motion_transform = (t->skeleton->get_bone_rest(t->bone_idx) * root_motion_transform) * t->skeleton->get_bone_rest(t->bone_idx).affine_inverse();
						}
					} else if (t->skeleton && t->bone_idx >= 0) {

						t->skeleton->set_bone_pose(t->bone_idx, xform);

					} else {

						t->spatial->set_transform(xform);
					}

				} break;
				case Animation::TYPE_VALUE: {

					TrackCacheValue *t = static_cast<TrackCacheValue *>(track);

					t->object->set_indexed(t->subpath, t->value);

				} break;
				case Animation::TYPE_BEZIER: {

					TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track);

					t->object->set_indexed(t->subpath, t->value);

				} break;
				default: {
				} //the rest don't matter
			}
		}
	}
}
void AnimationNodeBlendTreeEditor::_notification(int p_what) {

	if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {

		goto_parent->set_icon(get_icon("MoveUp", "EditorIcons"));

		error_panel->add_style_override("panel", get_stylebox("bg", "Tree"));
		error_label->add_color_override("font_color", get_color("error_color", "Editor"));
	}

	if (p_what == NOTIFICATION_PROCESS) {

		String error;

		if (!blend_tree->get_tree()) {
			error = TTR("BlendTree does not belong to an AnimationTree node.");
		} else if (!blend_tree->get_tree()->is_active()) {
			error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
		} else if (blend_tree->get_tree()->is_state_invalid()) {
			error = blend_tree->get_tree()->get_invalid_state_reason();
		}

		if (error != error_label->get_text()) {
			error_label->set_text(error);
			if (error != String()) {
				error_panel->show();
			} else {
				error_panel->hide();
			}
		}

		List<AnimationNodeBlendTree::NodeConnection> conns;
		blend_tree->get_node_connections(&conns);
		for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = conns.front(); E; E = E->next()) {
			float activity = 0;
			if (blend_tree->get_tree() && !blend_tree->get_tree()->is_state_invalid()) {
				activity = blend_tree->get_connection_activity(E->get().input_node, E->get().input_index);
			}
			graph->set_connection_activity(E->get().output_node, 0, E->get().input_node, E->get().input_index, activity);
		}

		AnimationTree *graph_player = blend_tree->get_tree();
		AnimationPlayer *player = NULL;
		if (graph_player->has_node(graph_player->get_animation_player())) {
			player = Object::cast_to<AnimationPlayer>(graph_player->get_node(graph_player->get_animation_player()));
		}

		if (player) {
			for (Map<StringName, ProgressBar *>::Element *E = animations.front(); E; E = E->next()) {
				Ref<AnimationNodeAnimation> an = blend_tree->get_node(E->key());
				if (an.is_valid()) {
					if (player->has_animation(an->get_animation())) {
						Ref<Animation> anim = player->get_animation(an->get_animation());
						if (anim.is_valid()) {
							E->get()->set_max(anim->get_length());
							E->get()->set_value(an->get_playback_time());
						}
					}
				}
			}
		}
	}
}
Exemplo n.º 28
0
void AnimationTreeEditor::_popup_edit_dialog() {

	updating_edit=true;

	for(int i=0;i<2;i++)
		edit_scroll[i]->hide();

	for(int i=0;i<4;i++) {

		edit_line[i]->hide();
		edit_label[i]->hide();
	}

	edit_option->hide();
	edit_button->hide();;
	filter_button->hide();
	edit_check->hide();;

	Point2 pos = anim_tree->node_get_pos(edited_node)-Point2(h_scroll->get_val(),v_scroll->get_val());
	Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
	Size2 size = get_node_size(edited_node);
	Point2 popup_pos( pos.x+style->get_margin(MARGIN_LEFT), pos.y+size.y-style->get_margin(MARGIN_BOTTOM));
	popup_pos+=get_global_pos();

	if (renaming_edit) {

		edit_label[0]->set_text("New name:");
		edit_label[0]->set_pos(Point2(5,5));
		edit_label[0]->show();
		edit_line[0]->set_begin(Point2(15,25));
		edit_line[0]->set_text(edited_node);
		edit_line[0]->show();
		edit_dialog->set_size(Size2(150,50));

	} else {

		AnimationTreePlayer::NodeType type=anim_tree->node_get_type(edited_node);


		switch(type) {

			case AnimationTreePlayer::NODE_ANIMATION:

				if (anim_tree->get_master_player()!=NodePath() && anim_tree->has_node(anim_tree->get_master_player())  && anim_tree->get_node(anim_tree->get_master_player())->cast_to<AnimationPlayer>()) {

					AnimationPlayer *ap = anim_tree->get_node(anim_tree->get_master_player())->cast_to<AnimationPlayer>();
					master_anim_popup->clear();
					List<StringName> sn;
					ap->get_animation_list(&sn);
					sn.sort_custom<StringName::AlphCompare>();
					for (List<StringName>::Element *E=sn.front();E;E=E->next()) {
						master_anim_popup->add_item(E->get());
					}

					master_anim_popup->set_pos(popup_pos);
					master_anim_popup->popup();
				} else {
					property_editor->edit(this,"",Variant::OBJECT,anim_tree->animation_node_get_animation(edited_node),PROPERTY_HINT_RESOURCE_TYPE,"Animation");
					property_editor->set_pos(popup_pos);
					property_editor->popup();
					updating_edit=false;
				}
				return;
			 case AnimationTreePlayer::NODE_TIMESCALE:
				edit_label[0]->set_text("Scale:");
				edit_label[0]->set_pos(Point2(5,5));
				edit_label[0]->show();
				edit_line[0]->set_begin(Point2(15,25));
				edit_line[0]->set_text(rtos(anim_tree->timescale_node_get_scale(edited_node)));
				edit_line[0]->show();
				edit_dialog->set_size(Size2(150,50));
				break;
			 case AnimationTreePlayer::NODE_ONESHOT:
				edit_label[0]->set_text("Fade In (s):");
				edit_label[0]->set_pos(Point2(5,5));
				edit_label[0]->show();
				edit_line[0]->set_begin(Point2(15,25));
				edit_line[0]->set_text(rtos(anim_tree->oneshot_node_get_fadein_time(edited_node)));
				edit_line[0]->show();
				edit_label[1]->set_text("Fade Out (s):");
				edit_label[1]->set_pos(Point2(5,55));
				edit_label[1]->show();
				edit_line[1]->set_begin(Point2(15,75));
				edit_line[1]->set_text(rtos(anim_tree->oneshot_node_get_fadeout_time(edited_node)));
				edit_line[1]->show();

				edit_option->clear();
				edit_option->add_item("Blend",0);
				edit_option->add_item("Mix",1);
				edit_option->set_begin(Point2(15,105));

				edit_option->select( anim_tree->oneshot_node_get_mix_mode(edited_node));
				edit_option->show();

				edit_check->set_text("Auto Restart:");
				edit_check->set_begin(Point2(15,125));
				edit_check->set_pressed(anim_tree->oneshot_node_has_autorestart(edited_node));
				edit_check->show();

				edit_label[2]->set_text("Restart (s):");
				edit_label[2]->set_pos(Point2(5,145));
				edit_label[2]->show();
				edit_line[2]->set_begin(Point2(15,165));
				edit_line[2]->set_text(rtos(anim_tree->oneshot_node_get_autorestart_delay(edited_node)));
				edit_line[2]->show();
				edit_label[3]->set_text("Random Restart (s):");
				edit_label[3]->set_pos(Point2(5,195));
				edit_label[3]->show();
				edit_line[3]->set_begin(Point2(15,215));
				edit_line[3]->set_text(rtos(anim_tree->oneshot_node_get_autorestart_random_delay(edited_node)));
				edit_line[3]->show();

				filter_button->set_begin(Point2(10,245));
				filter_button->show();

				edit_button->set_begin(Point2(10,268));
				edit_button->set_text("Start!");

				edit_button->show();

				edit_dialog->set_size(Size2(180,293));

				break;

			 case AnimationTreePlayer::NODE_MIX:

				 edit_label[0]->set_text("Amount:");
				 edit_label[0]->set_pos(Point2(5,5));
				 edit_label[0]->show();
				 edit_scroll[0]->set_min(0);
				 edit_scroll[0]->set_max(1);
				 edit_scroll[0]->set_val(anim_tree->mix_node_get_amount(edited_node));
				 edit_scroll[0]->set_begin(Point2(15,25));
				 edit_scroll[0]->show();
				 edit_dialog->set_size(Size2(150,50));

				 break;
			 case AnimationTreePlayer::NODE_BLEND2:
				 edit_label[0]->set_text("Blend:");
				 edit_label[0]->set_pos(Point2(5,5));
				 edit_label[0]->show();
				 edit_scroll[0]->set_min(0);
				 edit_scroll[0]->set_max(1);
				 edit_scroll[0]->set_val(anim_tree->blend2_node_get_amount(edited_node));
				 edit_scroll[0]->set_begin(Point2(15,25));
				 edit_scroll[0]->show();
				 filter_button->set_begin(Point2(10,47));
				 filter_button->show();
				 edit_dialog->set_size(Size2(150,74));

				 break;

			 case AnimationTreePlayer::NODE_BLEND3:
				 edit_label[0]->set_text("Blend:");
				 edit_label[0]->set_pos(Point2(5,5));
				 edit_label[0]->show();
				 edit_scroll[0]->set_min(-1);
				 edit_scroll[0]->set_max(1);
				 edit_scroll[0]->set_val(anim_tree->blend3_node_get_amount(edited_node));
				 edit_scroll[0]->set_begin(Point2(15,25));
				 edit_scroll[0]->show();
				 edit_dialog->set_size(Size2(150,50));

				 break;
			case AnimationTreePlayer::NODE_BLEND4:

				edit_label[0]->set_text("Blend 0:");
				edit_label[0]->set_pos(Point2(5,5));
				edit_label[0]->show();
				edit_scroll[0]->set_min(0);
				edit_scroll[0]->set_max(1);
				edit_scroll[0]->set_val(anim_tree->blend4_node_get_amount(edited_node).x);
				edit_scroll[0]->set_begin(Point2(15,25));
				edit_scroll[0]->show();
				edit_label[1]->set_text("Blend 1:");
				edit_label[1]->set_pos(Point2(5,55));
				edit_label[1]->show();
				edit_scroll[1]->set_min(0);
				edit_scroll[1]->set_max(1);
				edit_scroll[1]->set_val(anim_tree->blend4_node_get_amount(edited_node).y);
				edit_scroll[1]->set_begin(Point2(15,75));
				edit_scroll[1]->show();
				edit_dialog->set_size(Size2(150,100));

				break;

			 case AnimationTreePlayer::NODE_TRANSITION: {


				 edit_label[0]->set_text("X-Fade Time (s):");
				 edit_label[0]->set_pos(Point2(5,5));
				 edit_label[0]->show();
				 edit_line[0]->set_begin(Point2(15,25));
				 edit_line[0]->set_text(rtos(anim_tree->transition_node_get_xfade_time(edited_node)));
				 edit_line[0]->show();

				 edit_label[1]->set_text("Current:");
				 edit_label[1]->set_pos(Point2(5,55));
				 edit_label[1]->show();
				 edit_option->set_begin(Point2(15,75));

				 edit_option->clear();;

				 for(int i=0;i<anim_tree->transition_node_get_input_count(edited_node);i++) {
					 edit_option->add_item(itos(i),i);
				 }

				 edit_option->select(anim_tree->transition_node_get_current(edited_node));
				 edit_option->show();
				 edit_dialog->set_size(Size2(150,100));

			} break;
			default: {}

		}

	}



	edit_dialog->set_pos(popup_pos);
	edit_dialog->popup();

	updating_edit=false;
}
Exemplo n.º 29
0
AEResult GameLightsUpdate::ShadowLightRenderGameObject(GameObject* gameObject, const glm::mat4& lightView, const glm::mat4& lightProj)
{
	AEAssert(gameObject != nullptr);
	if (gameObject == nullptr)
	{
		return AEResult::NullParameter;
	}

	if (gameObject->HasMeshGOC() && gameObject->HasMaterialGOCs())
	{
		Mesh* mesh = gameObject->GetMeshGOC()->GetMeshResource();

		if (mesh != nullptr)
		{
			ConstantBuffer* cb = nullptr;
			Material* mat = nullptr;
			bool hasAnimation = gameObject->HasMeshAnimationGOC();

			if (hasAnimation)
			{
				mat = m_VarianceSkinningShadowMaterial;
				ShaderProperties* vsProps = m_VarianceSkinningShadowMaterial->GetVSProps();
				cb = vsProps->GetConstantBuffer(AE_CB_WORLD_VIEW_PROJ_NAME);

				ConstantBuffer* cbBones = vsProps->GetConstantBuffer(AE_CB_BONES_NAME);
				if (cbBones != nullptr)
				{
					AnimationPlayer* player = gameObject->GetMeshAnimationGOC()->GetAnimationPlayer();
					cbBones->SetValue(AE_CB_BONE_TRANSFORMS_VAR_NAME, player->GetBoneTransforms(), sizeof(glm::mat4) * AE_MAX_BONES);
				}
			}
			else
			{
				mat = m_VarianceShadowMaterial;
				ShaderProperties* vsProps = m_VarianceShadowMaterial->GetVSProps();
				cb = vsProps->GetConstantBuffer(AE_CB_WORLD_VIEW_PROJ_NAME);
			}

			cb->SetValueT<glm::mat4>(AE_CB_WORLD_VAR_NAME, gameObject->GetWorldTransform());
			cb->SetValueT<glm::mat4>(AE_CB_VIEW_VAR_NAME, lightView);
			cb->SetValueT<glm::mat4>(AE_CB_PROJECTION_VAR_NAME, lightProj);

			AETODO("check return");
			mat->Apply();

			for (uint32_t i = 0; i < mesh->GetNumberMeshParts(); i++)
			{
				MeshPart* meshPart = mesh->GetMeshPart(i);

				m_GraphicDevice->SetVertexBuffer(meshPart->GetVertexBuffer());
				m_GraphicDevice->SetIndexBuffer(meshPart->GetIndexBuffer());

				m_GraphicDevice->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

				m_GraphicDevice->DrawIndexed(0, 0, meshPart->GetIndexBuffer()->GetSize());
			}

			AETODO("check return");
			mat->UnApply();
		}
	}

	for (auto goIt : *gameObject)
	{
		ShadowLightRenderGameObject(goIt.second, lightView, lightProj);
	}

	return AEResult::Ok;
}
bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &anode) {

	if (updating || _filter_edit != anode)
		return false;

	NodePath player_path = anode->get_tree()->get_animation_player();

	if (!anode->get_tree()->has_node(player_path)) {
		EditorNode::get_singleton()->show_warning(TTR("No animation player set, so unable to retrieve track names."));
		return false;
	}

	AnimationPlayer *player = Object::cast_to<AnimationPlayer>(anode->get_tree()->get_node(player_path));
	if (!player) {
		EditorNode::get_singleton()->show_warning(TTR("Player path set is invalid, so unable to retrieve track names."));
		return false;
	}

	Node *base = player->get_node(player->get_root());

	if (!base) {
		EditorNode::get_singleton()->show_warning(TTR("Animation player has no valid root node path, so unable to retrieve track names."));
		return false;
	}

	updating = true;

	Set<String> paths;
	{
		List<StringName> animations;
		player->get_animation_list(&animations);

		for (List<StringName>::Element *E = animations.front(); E; E = E->next()) {

			Ref<Animation> anim = player->get_animation(E->get());
			for (int i = 0; i < anim->get_track_count(); i++) {
				paths.insert(anim->track_get_path(i));
			}
		}
	}

	filter_enabled->set_pressed(anode->is_filter_enabled());
	filters->clear();
	TreeItem *root = filters->create_item();

	Map<String, TreeItem *> parenthood;

	for (Set<String>::Element *E = paths.front(); E; E = E->next()) {

		NodePath path = E->get();
		TreeItem *ti = NULL;
		String accum;
		for (int i = 0; i < path.get_name_count(); i++) {
			String name = path.get_name(i);
			if (accum != String()) {
				accum += "/";
			}
			accum += name;
			if (!parenthood.has(accum)) {
				if (ti) {
					ti = filters->create_item(ti);
				} else {
					ti = filters->create_item(root);
				}
				parenthood[accum] = ti;
				ti->set_text(0, name);
				ti->set_selectable(0, false);
				ti->set_editable(0, false);

				if (base->has_node(accum)) {
					Node *node = base->get_node(accum);
					if (has_icon(node->get_class(), "EditorIcons")) {
						ti->set_icon(0, get_icon(node->get_class(), "EditorIcons"));
					} else {
						ti->set_icon(0, get_icon("Node", "EditorIcons"));
					}
				}

			} else {
				ti = parenthood[accum];
			}
		}

		Node *node = NULL;
		if (base->has_node(accum)) {
			node = base->get_node(accum);
		}
		if (!node)
			continue; //no node, cant edit

		if (path.get_subname_count()) {

			String concat = path.get_concatenated_subnames();

			Skeleton *skeleton = Object::cast_to<Skeleton>(node);
			if (skeleton && skeleton->find_bone(concat) != -1) {
				//path in skeleton
				String bone = concat;
				int idx = skeleton->find_bone(bone);
				List<String> bone_path;
				while (idx != -1) {
					bone_path.push_front(skeleton->get_bone_name(idx));
					idx = skeleton->get_bone_parent(idx);
				}

				accum += ":";
				for (List<String>::Element *F = bone_path.front(); F; F = F->next()) {
					if (F != bone_path.front()) {
						accum += "/";
					}

					accum += F->get();
					if (!parenthood.has(accum)) {
						ti = filters->create_item(ti);
						parenthood[accum] = ti;
						ti->set_text(0, F->get());
						ti->set_selectable(0, false);
						ti->set_editable(0, false);
						ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons"));
					} else {
						ti = parenthood[accum];
					}
				}

				ti->set_editable(0, true);
				ti->set_selectable(0, true);
				ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
				ti->set_text(0, concat);
				ti->set_checked(0, anode->is_path_filtered(path));
				ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons"));
				ti->set_metadata(0, path);

			} else {
				//just a property
				ti = filters->create_item(ti);
				ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
				ti->set_text(0, concat);
				ti->set_editable(0, true);
				ti->set_selectable(0, true);
				ti->set_checked(0, anode->is_path_filtered(path));
				ti->set_metadata(0, path);
			}
		} else {
			if (ti) {
				//just a node, likely call or animation track
				ti->set_editable(0, true);
				ti->set_selectable(0, true);
				ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
				ti->set_checked(0, anode->is_path_filtered(path));
				ti->set_metadata(0, path);
			}
		}
	}

	updating = false;

	return true;
}