forked from sascha/godot
-New inspector.
-Changed UI resizing code, gained huge amount of speed. -Reorganized timer sync to clean up behavior (sorry forgot commit this before) -3.1
parent
3b8bd50b41
commit
005b69cf6e
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,283 @@
|
||||
#ifndef EDITOR_INSPECTOR_H
|
||||
#define EDITOR_INSPECTOR_H
|
||||
|
||||
#include "editor_data.h"
|
||||
#include "scene/gui/scroll_container.h"
|
||||
|
||||
class EditorProperty : public Container {
|
||||
|
||||
GDCLASS(EditorProperty, Container)
|
||||
public:
|
||||
enum LabelLayout {
|
||||
LABEL_LAYOUT_LEFT,
|
||||
LABEL_LAYOUT_TOP,
|
||||
};
|
||||
|
||||
private:
|
||||
String label;
|
||||
int text_size;
|
||||
friend class EditorInspector;
|
||||
Object *object;
|
||||
StringName property;
|
||||
|
||||
LabelLayout label_layout;
|
||||
|
||||
int property_usage;
|
||||
|
||||
bool read_only;
|
||||
bool checkable;
|
||||
bool checked;
|
||||
bool draw_red;
|
||||
bool keying;
|
||||
|
||||
Rect2 keying_rect;
|
||||
bool keying_hover;
|
||||
Rect2 revert_rect;
|
||||
bool revert_hover;
|
||||
Rect2 check_rect;
|
||||
bool check_hover;
|
||||
|
||||
bool can_revert;
|
||||
|
||||
bool _might_be_in_instance();
|
||||
bool _is_property_different(const Variant &p_current, const Variant &p_orig, int p_usage);
|
||||
bool _is_instanced_node_with_original_property_different();
|
||||
bool _get_instanced_node_original_property(const StringName &p_prop, Variant &value);
|
||||
void _focusable_focused(int p_index);
|
||||
|
||||
bool selected;
|
||||
int selected_focusable;
|
||||
|
||||
Vector<Control *> focusables;
|
||||
Control *label_reference;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
void _gui_input(const Ref<InputEvent> &p_event);
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const;
|
||||
|
||||
void set_label(const String &p_label);
|
||||
String get_label() const;
|
||||
|
||||
void set_read_only(bool p_read_only);
|
||||
bool is_read_only() const;
|
||||
|
||||
Object *get_edited_object();
|
||||
StringName get_edited_property();
|
||||
|
||||
virtual void update_property();
|
||||
void update_reload_status();
|
||||
|
||||
virtual bool use_keying_next() const;
|
||||
|
||||
void set_checkable(bool p_checkable);
|
||||
bool is_checkable() const;
|
||||
|
||||
void set_checked(bool p_checked);
|
||||
bool is_checked() const;
|
||||
|
||||
void set_draw_red(bool p_draw_red);
|
||||
bool is_draw_red() const;
|
||||
|
||||
void set_keying(bool p_keying);
|
||||
bool is_keying() const;
|
||||
|
||||
void add_focusable(Control *p_control);
|
||||
void select(int p_focusable = -1);
|
||||
void deselect();
|
||||
bool is_selected() const;
|
||||
|
||||
void set_label_reference(Control *p_control);
|
||||
|
||||
virtual Variant get_drag_data(const Point2 &p_point);
|
||||
|
||||
void set_label_layout(LabelLayout p_layout);
|
||||
EditorProperty();
|
||||
};
|
||||
|
||||
class EditorInspectorPlugin : public Reference {
|
||||
GDCLASS(EditorInspectorPlugin, Reference)
|
||||
|
||||
friend class EditorInspector;
|
||||
struct AddedEditor {
|
||||
Control *property_editor;
|
||||
Vector<String> properties;
|
||||
String label;
|
||||
};
|
||||
|
||||
List<AddedEditor> added_editors;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void add_custom_control(Control *control);
|
||||
void add_property_editor(const String &p_for_property, Control *p_prop);
|
||||
void add_property_editor_for_multiple_properties(const String &p_label, const Vector<String> &p_properties, Control *p_prop);
|
||||
|
||||
virtual bool can_handle(Object *p_object);
|
||||
virtual void parse_begin(Object *p_object);
|
||||
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
|
||||
virtual void parse_end();
|
||||
};
|
||||
|
||||
class EditorInspectorCategory : public Control {
|
||||
GDCLASS(EditorInspectorCategory, Control);
|
||||
|
||||
friend class EditorInspector;
|
||||
Ref<Texture> icon;
|
||||
String label;
|
||||
Color bg_color;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const;
|
||||
|
||||
EditorInspectorCategory();
|
||||
};
|
||||
|
||||
class EditorInspectorSection : public Container {
|
||||
GDCLASS(EditorInspectorSection, Container);
|
||||
|
||||
String label;
|
||||
String section;
|
||||
Object *object;
|
||||
VBoxContainer *vbox;
|
||||
Color bg_color;
|
||||
bool foldable;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
void _gui_input(const Ref<InputEvent> &p_event);
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const;
|
||||
|
||||
void setup(const String &p_section, const String &p_label, Object *p_object, const Color &p_bg_color, bool p_foldable);
|
||||
VBoxContainer *get_vbox();
|
||||
void unfold();
|
||||
void fold();
|
||||
|
||||
Object *get_edited_object();
|
||||
|
||||
EditorInspectorSection();
|
||||
};
|
||||
|
||||
class EditorInspector : public ScrollContainer {
|
||||
GDCLASS(EditorInspector, ScrollContainer);
|
||||
|
||||
UndoRedo *undo_redo;
|
||||
enum {
|
||||
MAX_PLUGINS = 1024
|
||||
};
|
||||
static Ref<EditorInspectorPlugin> inspector_plugins[MAX_PLUGINS];
|
||||
static int inspector_plugin_count;
|
||||
|
||||
VBoxContainer *main_vbox;
|
||||
|
||||
//map use to cache the instanced editors
|
||||
Map<StringName, List<EditorProperty *> > editor_property_map;
|
||||
List<EditorInspectorSection *> sections;
|
||||
Set<StringName> pending;
|
||||
|
||||
void _clear();
|
||||
Object *object;
|
||||
|
||||
//
|
||||
|
||||
LineEdit *search_box;
|
||||
bool show_categories;
|
||||
bool hide_script;
|
||||
bool use_doc_hints;
|
||||
bool capitalize_paths;
|
||||
bool use_filter;
|
||||
bool autoclear;
|
||||
bool use_folding;
|
||||
int changing;
|
||||
bool update_all_pending;
|
||||
bool read_only;
|
||||
bool keying;
|
||||
|
||||
int refresh_countdown;
|
||||
bool update_tree_pending;
|
||||
StringName _prop_edited;
|
||||
StringName property_selected;
|
||||
int property_focusable;
|
||||
|
||||
Map<StringName, Map<StringName, String> > descr_cache;
|
||||
Map<StringName, String> class_descr_cache;
|
||||
|
||||
void _edit_set(const String &p_name, const Variant &p_value, bool p_refresh_all, const String &p_changed_field);
|
||||
|
||||
void _property_changed(const String &p_path, const Variant &p_value);
|
||||
void _multiple_properties_changed(Vector<String> p_paths, Array p_values);
|
||||
void _property_keyed(const String &p_path);
|
||||
void _property_checked(const String &p_path, bool p_checked);
|
||||
|
||||
void _resource_selected(const String &p_path, RES p_resource);
|
||||
void _property_selected(const String &p_path, int p_focusable);
|
||||
void _object_id_selected(const String &p_path, ObjectID p_id);
|
||||
|
||||
void _node_removed(Node *p_node);
|
||||
|
||||
void _changed_callback(Object *p_changed, const char *p_prop);
|
||||
void _edit_request_change(Object *p_changed, const String &p_prop);
|
||||
|
||||
void _filter_changed(const String &p_text);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
static void add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin);
|
||||
static void remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin);
|
||||
static void cleanup_plugins();
|
||||
|
||||
void set_undo_redo(UndoRedo *p_undo_redo);
|
||||
|
||||
String get_selected_path() const;
|
||||
|
||||
void update_tree();
|
||||
void update_property(const String &p_prop);
|
||||
|
||||
void refresh();
|
||||
|
||||
void edit(Object *p_object);
|
||||
|
||||
void set_keying(bool p_active);
|
||||
void set_read_only(bool p_read_only);
|
||||
|
||||
bool is_capitalize_paths_enabled() const;
|
||||
void set_enable_capitalize_paths(bool p_capitalize);
|
||||
void set_autoclear(bool p_enable);
|
||||
|
||||
void set_show_categories(bool p_show);
|
||||
void set_use_doc_hints(bool p_enable);
|
||||
void set_hide_script(bool p_hide);
|
||||
|
||||
void set_use_filter(bool p_use);
|
||||
void register_text_enter(Node *p_line_edit);
|
||||
|
||||
void set_subsection_selectable(bool p_selectable);
|
||||
void set_property_selectable(bool p_selectable);
|
||||
|
||||
void set_use_folding(bool p_enable);
|
||||
|
||||
void collapse_all_folding();
|
||||
void expand_all_folding();
|
||||
|
||||
void set_scroll_offset(int p_offset);
|
||||
int get_scroll_offset() const;
|
||||
|
||||
EditorInspector();
|
||||
};
|
||||
|
||||
#endif // INSPECTOR_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,490 @@
|
||||
#ifndef EDITOR_PROPERTIES_H
|
||||
#define EDITOR_PROPERTIES_H
|
||||
|
||||
#include "editor/create_dialog.h"
|
||||
#include "editor/editor_file_system.h"
|
||||
#include "editor/editor_inspector.h"
|
||||
#include "editor/editor_spin_slider.h"
|
||||
#include "editor/property_selector.h"
|
||||
#include "editor/scene_tree_editor.h"
|
||||
#include "scene/gui/color_picker.h"
|
||||
|
||||
class EditorPropertyText : public EditorProperty {
|
||||
GDCLASS(EditorPropertyText, EditorProperty)
|
||||
LineEdit *text;
|
||||
|
||||
bool updating;
|
||||
void _text_changed(const String &p_string);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
EditorPropertyText();
|
||||
};
|
||||
|
||||
class EditorPropertyMultilineText : public EditorProperty {
|
||||
GDCLASS(EditorPropertyMultilineText, EditorProperty)
|
||||
TextEdit *text;
|
||||
|
||||
AcceptDialog *big_text_dialog;
|
||||
TextEdit *big_text;
|
||||
Button *open_big_text;
|
||||
|
||||
void _big_text_changed();
|
||||
void _text_changed();
|
||||
void _open_big_text();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
EditorPropertyMultilineText();
|
||||
};
|
||||
|
||||
class EditorPropertyTextEnum : public EditorProperty {
|
||||
GDCLASS(EditorPropertyTextEnum, EditorProperty)
|
||||
OptionButton *options;
|
||||
|
||||
void _option_selected(int p_which);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void setup(const Vector<String> &p_options);
|
||||
virtual void update_property();
|
||||
EditorPropertyTextEnum();
|
||||
};
|
||||
|
||||
class EditorPropertyPath : public EditorProperty {
|
||||
GDCLASS(EditorPropertyPath, EditorProperty)
|
||||
Vector<String> extensions;
|
||||
bool folder;
|
||||
bool global;
|
||||
EditorFileDialog *dialog;
|
||||
Button *path;
|
||||
|
||||
void _path_selected(const String &p_path);
|
||||
void _path_pressed();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void setup(const Vector<String> &p_extensions, bool p_folder, bool p_global);
|
||||
virtual void update_property();
|
||||
EditorPropertyPath();
|
||||
};
|
||||
|
||||
class EditorPropertyMember : public EditorProperty {
|
||||
GDCLASS(EditorPropertyMember, EditorProperty)
|
||||
public:
|
||||
enum Type {
|
||||
MEMBER_METHOD_OF_VARIANT_TYPE, ///< a method of a type
|
||||
MEMBER_METHOD_OF_BASE_TYPE, ///< a method of a base type
|
||||
MEMBER_METHOD_OF_INSTANCE, ///< a method of an instance
|
||||
MEMBER_METHOD_OF_SCRIPT, ///< a method of a script & base
|
||||
MEMBER_PROPERTY_OF_VARIANT_TYPE, ///< a property of a type
|
||||
MEMBER_PROPERTY_OF_BASE_TYPE, ///< a property of a base type
|
||||
MEMBER_PROPERTY_OF_INSTANCE, ///< a property of an instance
|
||||
MEMBER_PROPERTY_OF_SCRIPT, ///< a property of a script & base
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
Type hint;
|
||||
PropertySelector *selector;
|
||||
Button *property;
|
||||
String hint_text;
|
||||
|
||||
void _property_selected(const String &p_selected);
|
||||
void _property_select();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void setup(Type p_hint, const String &p_hint_text);
|
||||
virtual void update_property();
|
||||
EditorPropertyMember();
|
||||
};
|
||||
|
||||
class EditorPropertyCheck : public EditorProperty {
|
||||
GDCLASS(EditorPropertyCheck, EditorProperty)
|
||||
CheckBox *checkbox;
|
||||
|
||||
void _checkbox_pressed();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
EditorPropertyCheck();
|
||||
};
|
||||
|
||||
class EditorPropertyEnum : public EditorProperty {
|
||||
GDCLASS(EditorPropertyEnum, EditorProperty)
|
||||
OptionButton *options;
|
||||
|
||||
void _option_selected(int p_which);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void setup(const Vector<String> &p_options);
|
||||
virtual void update_property();
|
||||
EditorPropertyEnum();
|
||||
};
|
||||
|
||||
class EditorPropertyFlags : public EditorProperty {
|
||||
GDCLASS(EditorPropertyFlags, EditorProperty)
|
||||
VBoxContainer *vbox;
|
||||
Vector<CheckBox *> flags;
|
||||
Vector<int> flag_indices;
|
||||
|
||||
void _flag_toggled();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void setup(const Vector<String> &p_options);
|
||||
virtual void update_property();
|
||||
EditorPropertyFlags();
|
||||
};
|
||||
|
||||
class EditorPropertyLayersGrid;
|
||||
|
||||
class EditorPropertyLayers : public EditorProperty {
|
||||
GDCLASS(EditorPropertyLayers, EditorProperty)
|
||||
public:
|
||||
enum LayerType {
|
||||
LAYER_PHYSICS_2D,
|
||||
LAYER_RENDER_2D,
|
||||
LAYER_PHYSICS_3D,
|
||||
LAYER_RENDER_3D,
|
||||
};
|
||||
|
||||
private:
|
||||
EditorPropertyLayersGrid *grid;
|
||||
void _grid_changed(uint32_t p_grid);
|
||||
LayerType layer_type;
|
||||
PopupMenu *layers;
|
||||
Button *button;
|
||||
|
||||
void _button_pressed();
|
||||
void _menu_pressed(int p_menu);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void setup(LayerType p_layer_type);
|
||||
virtual void update_property();
|
||||
EditorPropertyLayers();
|
||||
};
|
||||
|
||||
class EditorPropertyInteger : public EditorProperty {
|
||||
GDCLASS(EditorPropertyInteger, EditorProperty)
|
||||
EditorSpinSlider *spin;
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(int p_min, int p_max);
|
||||
EditorPropertyInteger();
|
||||
};
|
||||
|
||||
class EditorPropertyObjectID : public EditorProperty {
|
||||
GDCLASS(EditorPropertyObjectID, EditorProperty)
|
||||
Button *edit;
|
||||
String base_type;
|
||||
void _edit_pressed();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(const String &p_base_type);
|
||||
EditorPropertyObjectID();
|
||||
};
|
||||
|
||||
class EditorPropertyFloat : public EditorProperty {
|
||||
GDCLASS(EditorPropertyFloat, EditorProperty)
|
||||
EditorSpinSlider *spin;
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_exp_range);
|
||||
EditorPropertyFloat();
|
||||
};
|
||||
|
||||
class EditorPropertyEasing : public EditorProperty {
|
||||
GDCLASS(EditorPropertyEasing, EditorProperty)
|
||||
Control *easing_draw;
|
||||
ToolButton *button_out, *button_in, *button_linear, *button_constant;
|
||||
ToolButton *button_in_out, *button_out_in;
|
||||
VBoxContainer *vb;
|
||||
|
||||
bool flip;
|
||||
|
||||
void _drag_easing(const Ref<InputEvent> &p_ev);
|
||||
void _draw_easing();
|
||||
void _notification(int p_what);
|
||||
void _set_preset(float p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(bool p_full, bool p_flip);
|
||||
EditorPropertyEasing();
|
||||
};
|
||||
|
||||
class EditorPropertyVector2 : public EditorProperty {
|
||||
GDCLASS(EditorPropertyVector2, EditorProperty)
|
||||
EditorSpinSlider *spin[2];
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||
EditorPropertyVector2();
|
||||
};
|
||||
|
||||
class EditorPropertyRect2 : public EditorProperty {
|
||||
GDCLASS(EditorPropertyRect2, EditorProperty)
|
||||
EditorSpinSlider *spin[4];
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||
EditorPropertyRect2();
|
||||
};
|
||||
|
||||
class EditorPropertyVector3 : public EditorProperty {
|
||||
GDCLASS(EditorPropertyVector3, EditorProperty)
|
||||
EditorSpinSlider *spin[3];
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||
EditorPropertyVector3();
|
||||
};
|
||||
|
||||
class EditorPropertyPlane : public EditorProperty {
|
||||
GDCLASS(EditorPropertyPlane, EditorProperty)
|
||||
EditorSpinSlider *spin[4];
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||
EditorPropertyPlane();
|
||||
};
|
||||
|
||||
class EditorPropertyQuat : public EditorProperty {
|
||||
GDCLASS(EditorPropertyQuat, EditorProperty)
|
||||
EditorSpinSlider *spin[4];
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||
EditorPropertyQuat();
|
||||
};
|
||||
|
||||
class EditorPropertyAABB : public EditorProperty {
|
||||
GDCLASS(EditorPropertyAABB, EditorProperty)
|
||||
EditorSpinSlider *spin[6];
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||
EditorPropertyAABB();
|
||||
};
|
||||
|
||||
class EditorPropertyTransform2D : public EditorProperty {
|
||||
GDCLASS(EditorPropertyTransform2D, EditorProperty)
|
||||
EditorSpinSlider *spin[6];
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||
EditorPropertyTransform2D();
|
||||
};
|
||||
|
||||
class EditorPropertyBasis : public EditorProperty {
|
||||
GDCLASS(EditorPropertyBasis, EditorProperty)
|
||||
EditorSpinSlider *spin[9];
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||
EditorPropertyBasis();
|
||||
};
|
||||
|
||||
class EditorPropertyTransform : public EditorProperty {
|
||||
GDCLASS(EditorPropertyTransform, EditorProperty)
|
||||
EditorSpinSlider *spin[12];
|
||||
bool setting;
|
||||
void _value_changed(double p_val);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||
EditorPropertyTransform();
|
||||
};
|
||||
|
||||
class EditorPropertyColor : public EditorProperty {
|
||||
GDCLASS(EditorPropertyColor, EditorProperty)
|
||||
ColorPickerButton *picker;
|
||||
void _color_changed(const Color &p_color);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(bool p_show_alpha);
|
||||
EditorPropertyColor();
|
||||
};
|
||||
|
||||
class EditorPropertyNodePath : public EditorProperty {
|
||||
GDCLASS(EditorPropertyNodePath, EditorProperty)
|
||||
Button *assign;
|
||||
Button *clear;
|
||||
SceneTreeDialog *scene_tree;
|
||||
NodePath base_hint;
|
||||
|
||||
void _node_selected(const NodePath &p_path);
|
||||
void _node_assign();
|
||||
void _node_clear();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(const NodePath &p_base_hint);
|
||||
EditorPropertyNodePath();
|
||||
};
|
||||
|
||||
class EditorPropertyResource : public EditorProperty {
|
||||
GDCLASS(EditorPropertyResource, EditorProperty)
|
||||
|
||||
enum MenuOption {
|
||||
|
||||
OBJ_MENU_LOAD = 0,
|
||||
OBJ_MENU_EDIT = 1,
|
||||
OBJ_MENU_CLEAR = 2,
|
||||
OBJ_MENU_MAKE_UNIQUE = 3,
|
||||
OBJ_MENU_COPY = 4,
|
||||
OBJ_MENU_PASTE = 5,
|
||||
OBJ_MENU_NEW_SCRIPT = 6,
|
||||
OBJ_MENU_SHOW_IN_FILE_SYSTEM = 7,
|
||||
TYPE_BASE_ID = 100,
|
||||
CONVERT_BASE_ID = 1000
|
||||
|
||||
};
|
||||
|
||||
Button *assign;
|
||||
Button *edit;
|
||||
PopupMenu *menu;
|
||||
EditorFileDialog *file;
|
||||
Vector<String> inheritors_array;
|
||||
|
||||
String base_type;
|
||||
|
||||
SceneTreeDialog *scene_tree;
|
||||
|
||||
void _file_selected(const String &p_path);
|
||||
void _menu_option(int p_which);
|
||||
void _resource_preview(const String &p_path, const Ref<Texture> &p_preview, ObjectID p_obj);
|
||||
void _resource_selected();
|
||||
void _viewport_selected(const NodePath &p_path);
|
||||
|
||||
void _update_menu();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
virtual void update_property();
|
||||
void setup(const String &p_base_type);
|
||||
EditorPropertyResource();
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
/// \brief The EditorInspectorDefaultPlugin class
|
||||
///
|
||||
class EditorInspectorDefaultPlugin : public EditorInspectorPlugin {
|
||||
GDCLASS(EditorInspectorDefaultPlugin, EditorInspectorPlugin)
|
||||
|
||||
public:
|
||||
virtual bool can_handle(Object *p_object);
|
||||
virtual void parse_begin(Object *p_object);
|
||||
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
|
||||
virtual void parse_end();
|
||||
};
|
||||
|
||||
#endif // EDITOR_PROPERTIES_H
|
||||
@ -0,0 +1,315 @@
|
||||
#include "editor_spin_slider.h"
|
||||
#include "editor_scale.h"
|
||||
#include "os/input.h"
|
||||
String EditorSpinSlider::get_text_value() const {
|
||||
int zeros = Math::step_decimals(get_step());
|
||||
return String::num(get_value(), zeros);
|
||||
}
|
||||
void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
Ref<InputEventMouseButton> mb = p_event;
|
||||
if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
|
||||
|
||||
if (mb->is_pressed()) {
|
||||
|
||||
if (updown_offset != -1 && mb->get_position().x > updown_offset) {
|
||||
//there is an updown, so use it.
|
||||
if (mb->get_position().y < get_size().height / 2) {
|
||||
set_value(get_value() + get_step());
|
||||
} else {
|
||||
set_value(get_value() - get_step());
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
|
||||
grabbing_spinner_attempt = true;
|
||||
grabbing_spinner = false;
|
||||
grabbing_spinner_mouse_pos = Input::get_singleton()->get_mouse_position();
|
||||
}
|
||||
} else {
|
||||
|
||||
if (grabbing_spinner_attempt) {
|
||||
|
||||
if (grabbing_spinner) {
|
||||
|
||||
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
|
||||
Input::get_singleton()->warp_mouse_position(grabbing_spinner_mouse_pos);
|
||||
update();
|
||||
} else {
|
||||
Rect2 gr = get_global_rect();
|
||||
value_input->set_text(get_text_value());
|
||||
value_input->set_position(gr.position);
|
||||
value_input->set_size(gr.size);
|
||||
value_input->call_deferred("show_modal");
|
||||
value_input->call_deferred("grab_focus");
|
||||
value_input->call_deferred("select_all");
|
||||
}
|
||||
|
||||
grabbing_spinner = false;
|
||||
grabbing_spinner_attempt = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<InputEventMouseMotion> mm = p_event;
|
||||
if (mm.is_valid()) {
|
||||
|
||||
if (grabbing_spinner_attempt) {
|
||||
|
||||
if (!grabbing_spinner) {
|
||||
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
|
||||
grabbing_spinner = true;
|
||||
}
|
||||
|
||||
double v = get_value();
|
||||
|
||||
double diff_x = mm->get_relative().x;
|
||||
diff_x = Math::pow(ABS(diff_x), 1.8f) * SGN(diff_x);
|
||||
diff_x *= 0.1;
|
||||
|
||||
v += diff_x * get_step();
|
||||
|
||||
set_value(v);
|
||||
|
||||
} else if (updown_offset != -1) {
|
||||
bool new_hover = (mm->get_position().x > updown_offset);
|
||||
if (new_hover != hover_updown) {
|
||||
hover_updown = new_hover;
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<InputEventKey> k = p_event;
|
||||
if (k.is_valid() && k->is_pressed() && k->is_action("ui_accept")) {
|
||||
Rect2 gr = get_global_rect();
|
||||
value_input->set_text(get_text_value());
|
||||
value_input->set_position(gr.position);
|
||||
value_input->set_size(gr.size);
|
||||
value_input->call_deferred("show_modal");
|
||||
value_input->call_deferred("grab_focus");
|
||||
value_input->call_deferred("select_all");
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSpinSlider::_value_input_closed() {
|
||||
set_value(value_input->get_text().to_double());
|
||||
}
|
||||
|
||||
void EditorSpinSlider::_value_input_entered(const String &p_text) {
|
||||
set_value(p_text.to_double());
|
||||
value_input->hide();
|
||||
}
|
||||
|
||||
void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
Ref<InputEventMouseButton> mb = p_event;
|
||||
if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
|
||||
|
||||
if (mb->is_pressed()) {
|
||||
|
||||
grabbing_grabber = true;
|
||||
grabbing_ratio = get_as_ratio();
|
||||
grabbing_from = grabber->get_transform().xform(mb->get_position()).x;
|
||||
} else {
|
||||
grabbing_grabber = false;
|
||||
}
|
||||
}
|
||||
|
||||
Ref<InputEventMouseMotion> mm = p_event;
|
||||
if (mm.is_valid() && grabbing_grabber) {
|
||||
|
||||
float grabbing_ofs = (grabber->get_transform().xform(mm->get_position()).x - grabbing_from) / float(grabber_range);
|
||||
set_as_ratio(grabbing_ratio + grabbing_ofs);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSpinSlider::_notification(int p_what) {
|
||||
|
||||
if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_OUT || p_what == MainLoop::NOTIFICATION_WM_FOCUS_OUT) {
|
||||
if (grabbing_spinner) {
|
||||
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
|
||||
grabbing_spinner = false;
|
||||
grabbing_spinner_attempt = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_DRAW) {
|
||||
|
||||
updown_offset = -1;
|
||||
|
||||
Ref<StyleBox> sb = get_stylebox("normal", "LineEdit");
|
||||
draw_style_box(sb, Rect2(Vector2(), get_size()));
|
||||
Ref<Font> font = get_font("font", "LineEdit");
|
||||
|
||||
int avail_width = get_size().width - sb->get_minimum_size().width - sb->get_minimum_size().width;
|
||||
avail_width -= font->get_string_size(label).width;
|
||||
Ref<Texture> updown = get_icon("updown", "SpinBox");
|
||||
|
||||
if (get_step() == 1) {
|
||||
avail_width -= updown->get_width();
|
||||
}
|
||||
|
||||
if (has_focus()) {
|
||||
Ref<StyleBox> focus = get_stylebox("focus", "LineEdit");
|
||||
draw_style_box(focus, Rect2(Vector2(), get_size()));
|
||||
}
|
||||
|
||||
String numstr = get_text_value();
|
||||
|
||||
int vofs = (get_size().height - font->get_height()) / 2 + font->get_ascent();
|
||||
|
||||
Color fc = get_color("font_color", "LineEdit");
|
||||
|
||||
int label_ofs = sb->get_offset().x + avail_width;
|
||||
draw_string(font, Vector2(label_ofs, vofs), label, fc * Color(1, 1, 1, 0.5));
|
||||
draw_string(font, Vector2(sb->get_offset().x, vofs), numstr, fc, avail_width);
|
||||
|
||||
if (get_step() == 1) {
|
||||
Ref<Texture> updown = get_icon("updown", "SpinBox");
|
||||
int updown_vofs = (get_size().height - updown->get_height()) / 2;
|
||||
updown_offset = get_size().width - sb->get_margin(MARGIN_RIGHT) - updown->get_width();
|
||||
Color c(1, 1, 1);
|
||||
if (hover_updown) {
|
||||
c *= Color(1.2, 1.2, 1.2);
|
||||
}
|
||||
draw_texture(updown, Vector2(updown_offset, updown_vofs), c);
|
||||
if (grabber->is_visible()) {
|
||||
grabber->hide();
|
||||
}
|
||||
} else if (!hide_slider) {
|
||||
int grabber_w = 4 * EDSCALE;
|
||||
int width = get_size().width - sb->get_minimum_size().width - grabber_w;
|
||||
int ofs = sb->get_offset().x;
|
||||
int svofs = (get_size().height + vofs) / 2 - 1;
|
||||
Color c = fc;
|
||||
c.a = 0.2;
|
||||
|
||||
draw_rect(Rect2(ofs, svofs + 1, width, 2 * EDSCALE), c);
|
||||
int gofs = get_as_ratio() * width;
|
||||
c.a = 0.9;
|
||||
Rect2 grabber_rect = Rect2(ofs + gofs, svofs + 1, grabber_w, 2 * EDSCALE);
|
||||
draw_rect(grabber_rect, c);
|
||||
|
||||
bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner;
|
||||
if (grabber->is_visible() != display_grabber) {
|
||||
if (display_grabber) {
|
||||
grabber->show();
|
||||
} else {
|
||||
grabber->hide();
|
||||
}
|
||||
}
|
||||
|
||||
if (display_grabber) {
|
||||
Ref<Texture> grabber_tex;
|
||||
if (mouse_over_grabber) {
|
||||
grabber_tex = get_icon("grabber_highlight", "HSlider");
|
||||
} else {
|
||||
grabber_tex = get_icon("grabber", "HSlider");
|
||||
}
|
||||
|
||||
if (grabber->get_texture() != grabber_tex) {
|
||||
grabber->set_texture(grabber_tex);
|
||||
}
|
||||
|
||||
grabber->set_size(Size2(0, 0));
|
||||
grabber->set_position(get_global_position() + grabber_rect.position + grabber_rect.size * 0.5 - grabber->get_size() * 0.5);
|
||||
grabber_range = width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_MOUSE_ENTER) {
|
||||
|
||||
mouse_over_spin = true;
|
||||
update();
|
||||
}
|
||||
if (p_what == NOTIFICATION_MOUSE_EXIT) {
|
||||
|
||||
mouse_over_spin = false;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
Size2 EditorSpinSlider::get_minimum_size() const {
|
||||
|
||||
Ref<StyleBox> sb = get_stylebox("normal", "LineEdit");
|
||||
Ref<Font> font = get_font("font", "LineEdit");
|
||||
|
||||
Size2 ms = sb->get_minimum_size();
|
||||
ms.height += font->get_height();
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
void EditorSpinSlider::set_hide_slider(bool p_hide) {
|
||||
hide_slider = p_hide;
|
||||
update();
|
||||
}
|
||||
|
||||
bool EditorSpinSlider::is_hiding_slider() const {
|
||||
return hide_slider;
|
||||
}
|
||||
|
||||
void EditorSpinSlider::set_label(const String &p_label) {
|
||||
label = p_label;
|
||||
update();
|
||||
}
|
||||
|
||||
String EditorSpinSlider::get_label() const {
|
||||
return label;
|
||||
}
|
||||
|
||||
void EditorSpinSlider::_grabber_mouse_entered() {
|
||||
mouse_over_grabber = true;
|
||||
update();
|
||||
}
|
||||
|
||||
void EditorSpinSlider::_grabber_mouse_exited() {
|
||||
mouse_over_grabber = false;
|
||||
update();
|
||||
}
|
||||
|
||||
void EditorSpinSlider::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_label", "label"), &EditorSpinSlider::set_label);
|
||||
ClassDB::bind_method(D_METHOD("get_label"), &EditorSpinSlider::get_label);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_gui_input"), &EditorSpinSlider::_gui_input);
|
||||
ClassDB::bind_method(D_METHOD("_grabber_mouse_entered"), &EditorSpinSlider::_grabber_mouse_entered);
|
||||
ClassDB::bind_method(D_METHOD("_grabber_mouse_exited"), &EditorSpinSlider::_grabber_mouse_exited);
|
||||
ClassDB::bind_method(D_METHOD("_grabber_gui_input"), &EditorSpinSlider::_grabber_gui_input);
|
||||
ClassDB::bind_method(D_METHOD("_value_input_closed"), &EditorSpinSlider::_value_input_closed);
|
||||
ClassDB::bind_method(D_METHOD("_value_input_entered"), &EditorSpinSlider::_value_input_entered);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label");
|
||||
}
|
||||
|
||||
EditorSpinSlider::EditorSpinSlider() {
|
||||
|
||||
grabbing_spinner_attempt = false;
|
||||
grabbing_spinner = false;
|
||||
|
||||
set_focus_mode(FOCUS_ALL);
|
||||
updown_offset = -1;
|
||||
hover_updown = false;
|
||||
grabber = memnew(TextureRect);
|
||||
add_child(grabber);
|
||||
grabber->hide();
|
||||
grabber->set_as_toplevel(true);
|
||||
grabber->set_mouse_filter(MOUSE_FILTER_STOP);
|
||||
grabber->connect("mouse_entered", this, "_grabber_mouse_entered");
|
||||
grabber->connect("mouse_exited", this, "_grabber_mouse_exited");
|
||||
grabber->connect("gui_input", this, "_grabber_gui_input");
|
||||
mouse_over_spin = false;
|
||||
mouse_over_grabber = false;
|
||||
grabbing_grabber = false;
|
||||
grabber_range = 1;
|
||||
value_input = memnew(LineEdit);
|
||||
add_child(value_input);
|
||||
value_input->set_as_toplevel(true);
|
||||
value_input->hide();
|
||||
value_input->connect("modal_closed", this, "_value_input_closed");
|
||||
value_input->connect("text_entered", this, "_value_input_entered");
|
||||
hide_slider = false;
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
#ifndef EDITOR_SPIN_SLIDER_H
|
||||
#define EDITOR_SPIN_SLIDER_H
|
||||
|
||||
#include "scene/gui/line_edit.h"
|
||||
#include "scene/gui/range.h"
|
||||
#include "scene/gui/texture_rect.h"
|
||||
|
||||
class EditorSpinSlider : public Range {
|
||||
GDCLASS(EditorSpinSlider, Range)
|
||||
|
||||
String label;
|
||||
int updown_offset;
|
||||
bool hover_updown;
|
||||
bool mouse_hover;
|
||||
|
||||
TextureRect *grabber;
|
||||
int grabber_range;
|
||||
|
||||
bool mouse_over_spin;
|
||||
bool mouse_over_grabber;
|
||||
|
||||
bool grabbing_grabber;
|
||||
int grabbing_from;
|
||||
float grabbing_ratio;
|
||||
|
||||
bool grabbing_spinner_attempt;
|
||||
bool grabbing_spinner;
|
||||
Vector2 grabbing_spinner_mouse_pos;
|
||||
|
||||
LineEdit *value_input;
|
||||
|
||||
void _grabber_gui_input(const Ref<InputEvent> &p_event);
|
||||
void _value_input_closed();
|
||||
void _value_input_entered(const String &);
|
||||
|
||||
bool hide_slider;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
void _gui_input(const Ref<InputEvent> &p_event);
|
||||
static void _bind_methods();
|
||||
void _grabber_mouse_entered();
|
||||
void _grabber_mouse_exited();
|
||||
|
||||
public:
|
||||
String get_text_value() const;
|
||||
void set_label(const String &p_label);
|
||||
String get_label() const;
|
||||
|
||||
void set_hide_slider(bool p_hide);
|
||||
bool is_hiding_slider() const;
|
||||
|
||||
virtual Size2 get_minimum_size() const;
|
||||
EditorSpinSlider();
|
||||
};
|
||||
|
||||
#endif // EDITOR_SPIN_SLIDER_H
|
||||
@ -1,5 +1,82 @@
|
||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 -1036.4)">
|
||||
<circle cx="8" cy="1044.4" r="3" fill="#fff" fill-opacity=".78431" stroke-linejoin="round" stroke-opacity=".39216" stroke-width="3"/>
|
||||
</g>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 15.999999"
|
||||
id="svg8"
|
||||
sodipodi:docname="icon_GUI_slider_grabber.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<metadata
|
||||
id="metadata14">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs12" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1211"
|
||||
inkscape:window-height="644"
|
||||
id="namedview10"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="-5.7627119"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-x="67"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g6" />
|
||||
<g
|
||||
transform="translate(0 -1036.4)"
|
||||
id="g6">
|
||||
<path
|
||||
transform="translate(0 1036.4)"
|
||||
d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 0.5 0.025391 5 5 0 0 1 0.49414 0.074219 5 5 0 0 1 0.48438 0.12305 5 5 0 0 1 0.46875 0.17188 5 5 0 0 1 0.44922 0.2168 5 5 0 0 1 0.42578 0.26172 5 5 0 0 1 0.39844 0.30273 5 5 0 0 1 0.36524 0.33984 5 5 0 0 1 0.33008 0.37695 5 5 0 0 1 0.29102 0.40625 5 5 0 0 1 0.24805 0.43359 5 5 0 0 1 0.20508 0.45508 5 5 0 0 1 0.1582 0.47461 5 5 0 0 1 0.10938 0.48828 5 5 0 0 1 0.060547 0.49609 5 5 0 0 1 0.011719 0.35352 5 5 0 0 1 -0.025391 0.5 5 5 0 0 1 -0.074218 0.49414 5 5 0 0 1 -0.12305 0.48438 5 5 0 0 1 -0.17188 0.46875 5 5 0 0 1 -0.2168 0.44922 5 5 0 0 1 -0.26172 0.42578 5 5 0 0 1 -0.30273 0.39844 5 5 0 0 1 -0.33984 0.36524 5 5 0 0 1 -0.37695 0.33008 5 5 0 0 1 -0.40625 0.29102 5 5 0 0 1 -0.43359 0.24805 5 5 0 0 1 -0.45508 0.20508 5 5 0 0 1 -0.47461 0.1582 5 5 0 0 1 -0.48828 0.10938 5 5 0 0 1 -0.49609 0.060547 5 5 0 0 1 -0.35352 0.011719 5 5 0 0 1 -0.5 -0.025391 5 5 0 0 1 -0.49414 -0.074218 5 5 0 0 1 -0.48438 -0.12305 5 5 0 0 1 -0.46875 -0.17188 5 5 0 0 1 -0.44922 -0.2168 5 5 0 0 1 -0.42578 -0.26172 5 5 0 0 1 -0.39844 -0.30273 5 5 0 0 1 -0.36523 -0.33984 5 5 0 0 1 -0.33008 -0.37695 5 5 0 0 1 -0.29102 -0.40625 5 5 0 0 1 -0.24805 -0.43359 5 5 0 0 1 -0.20508 -0.45508 5 5 0 0 1 -0.1582 -0.47461 5 5 0 0 1 -0.10938 -0.48828 5 5 0 0 1 -0.060547 -0.49609 5 5 0 0 1 -0.011719 -0.35352 5 5 0 0 1 0.025391 -0.5 5 5 0 0 1 0.074219 -0.49414 5 5 0 0 1 0.12305 -0.48438 5 5 0 0 1 0.17188 -0.46875 5 5 0 0 1 0.2168 -0.44922 5 5 0 0 1 0.26172 -0.42578 5 5 0 0 1 0.30273 -0.39844 5 5 0 0 1 0.33984 -0.36523 5 5 0 0 1 0.37695 -0.33008 5 5 0 0 1 0.40625 -0.29102 5 5 0 0 1 0.43359 -0.24805 5 5 0 0 1 0.45508 -0.20508 5 5 0 0 1 0.47461 -0.1582 5 5 0 0 1 0.48828 -0.10938 5 5 0 0 1 0.49609 -0.060547 5 5 0 0 1 0.35352 -0.011719z"
|
||||
fill="#e0e0e0"
|
||||
id="path2"
|
||||
style="fill:#e0e0e0;fill-opacity:0.28925619" />
|
||||
<circle
|
||||
cx="8"
|
||||
cy="1044.4"
|
||||
r="3"
|
||||
fill="#fff"
|
||||
fill-opacity=".58824"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-opacity=".32549"
|
||||
stroke-width="3"
|
||||
id="circle4" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-0.06779632,-1036.4)"
|
||||
id="g18">
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:0.78430996;stroke-width:3;stroke-linejoin:round;stroke-opacity:0.39216003"
|
||||
cx="8"
|
||||
cy="1044.4"
|
||||
r="3"
|
||||
id="circle16" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 288 B After Width: | Height: | Size: 3.9 KiB |
@ -1,6 +1,80 @@
|
||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 -1036.4)">
|
||||
<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 0.5 0.025391 5 5 0 0 1 0.49414 0.074219 5 5 0 0 1 0.48438 0.12305 5 5 0 0 1 0.46875 0.17188 5 5 0 0 1 0.44922 0.2168 5 5 0 0 1 0.42578 0.26172 5 5 0 0 1 0.39844 0.30273 5 5 0 0 1 0.36524 0.33984 5 5 0 0 1 0.33008 0.37695 5 5 0 0 1 0.29102 0.40625 5 5 0 0 1 0.24805 0.43359 5 5 0 0 1 0.20508 0.45508 5 5 0 0 1 0.1582 0.47461 5 5 0 0 1 0.10938 0.48828 5 5 0 0 1 0.060547 0.49609 5 5 0 0 1 0.011719 0.35352 5 5 0 0 1 -0.025391 0.5 5 5 0 0 1 -0.074218 0.49414 5 5 0 0 1 -0.12305 0.48438 5 5 0 0 1 -0.17188 0.46875 5 5 0 0 1 -0.2168 0.44922 5 5 0 0 1 -0.26172 0.42578 5 5 0 0 1 -0.30273 0.39844 5 5 0 0 1 -0.33984 0.36524 5 5 0 0 1 -0.37695 0.33008 5 5 0 0 1 -0.40625 0.29102 5 5 0 0 1 -0.43359 0.24805 5 5 0 0 1 -0.45508 0.20508 5 5 0 0 1 -0.47461 0.1582 5 5 0 0 1 -0.48828 0.10938 5 5 0 0 1 -0.49609 0.060547 5 5 0 0 1 -0.35352 0.011719 5 5 0 0 1 -0.5 -0.025391 5 5 0 0 1 -0.49414 -0.074218 5 5 0 0 1 -0.48438 -0.12305 5 5 0 0 1 -0.46875 -0.17188 5 5 0 0 1 -0.44922 -0.2168 5 5 0 0 1 -0.42578 -0.26172 5 5 0 0 1 -0.39844 -0.30273 5 5 0 0 1 -0.36523 -0.33984 5 5 0 0 1 -0.33008 -0.37695 5 5 0 0 1 -0.29102 -0.40625 5 5 0 0 1 -0.24805 -0.43359 5 5 0 0 1 -0.20508 -0.45508 5 5 0 0 1 -0.1582 -0.47461 5 5 0 0 1 -0.10938 -0.48828 5 5 0 0 1 -0.060547 -0.49609 5 5 0 0 1 -0.011719 -0.35352 5 5 0 0 1 0.025391 -0.5 5 5 0 0 1 0.074219 -0.49414 5 5 0 0 1 0.12305 -0.48438 5 5 0 0 1 0.17188 -0.46875 5 5 0 0 1 0.2168 -0.44922 5 5 0 0 1 0.26172 -0.42578 5 5 0 0 1 0.30273 -0.39844 5 5 0 0 1 0.33984 -0.36523 5 5 0 0 1 0.37695 -0.33008 5 5 0 0 1 0.40625 -0.29102 5 5 0 0 1 0.43359 -0.24805 5 5 0 0 1 0.45508 -0.20508 5 5 0 0 1 0.47461 -0.1582 5 5 0 0 1 0.48828 -0.10938 5 5 0 0 1 0.49609 -0.060547 5 5 0 0 1 0.35352 -0.011719z" fill="#e0e0e0"/>
|
||||
<circle cx="8" cy="1044.4" r="3" fill="#fff" fill-opacity=".58824" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".32549" stroke-width="3"/>
|
||||
</g>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 15.999999"
|
||||
id="svg8"
|
||||
sodipodi:docname="icon_GUI_slider_grabber_hl.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<metadata
|
||||
id="metadata14">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs12" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="944"
|
||||
inkscape:window-height="480"
|
||||
id="namedview10"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="8"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-x="67"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg8" />
|
||||
<g
|
||||
transform="translate(0 -1036.4)"
|
||||
id="g6">
|
||||
<path
|
||||
transform="translate(0 1036.4)"
|
||||
d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 0.5 0.025391 5 5 0 0 1 0.49414 0.074219 5 5 0 0 1 0.48438 0.12305 5 5 0 0 1 0.46875 0.17188 5 5 0 0 1 0.44922 0.2168 5 5 0 0 1 0.42578 0.26172 5 5 0 0 1 0.39844 0.30273 5 5 0 0 1 0.36524 0.33984 5 5 0 0 1 0.33008 0.37695 5 5 0 0 1 0.29102 0.40625 5 5 0 0 1 0.24805 0.43359 5 5 0 0 1 0.20508 0.45508 5 5 0 0 1 0.1582 0.47461 5 5 0 0 1 0.10938 0.48828 5 5 0 0 1 0.060547 0.49609 5 5 0 0 1 0.011719 0.35352 5 5 0 0 1 -0.025391 0.5 5 5 0 0 1 -0.074218 0.49414 5 5 0 0 1 -0.12305 0.48438 5 5 0 0 1 -0.17188 0.46875 5 5 0 0 1 -0.2168 0.44922 5 5 0 0 1 -0.26172 0.42578 5 5 0 0 1 -0.30273 0.39844 5 5 0 0 1 -0.33984 0.36524 5 5 0 0 1 -0.37695 0.33008 5 5 0 0 1 -0.40625 0.29102 5 5 0 0 1 -0.43359 0.24805 5 5 0 0 1 -0.45508 0.20508 5 5 0 0 1 -0.47461 0.1582 5 5 0 0 1 -0.48828 0.10938 5 5 0 0 1 -0.49609 0.060547 5 5 0 0 1 -0.35352 0.011719 5 5 0 0 1 -0.5 -0.025391 5 5 0 0 1 -0.49414 -0.074218 5 5 0 0 1 -0.48438 -0.12305 5 5 0 0 1 -0.46875 -0.17188 5 5 0 0 1 -0.44922 -0.2168 5 5 0 0 1 -0.42578 -0.26172 5 5 0 0 1 -0.39844 -0.30273 5 5 0 0 1 -0.36523 -0.33984 5 5 0 0 1 -0.33008 -0.37695 5 5 0 0 1 -0.29102 -0.40625 5 5 0 0 1 -0.24805 -0.43359 5 5 0 0 1 -0.20508 -0.45508 5 5 0 0 1 -0.1582 -0.47461 5 5 0 0 1 -0.10938 -0.48828 5 5 0 0 1 -0.060547 -0.49609 5 5 0 0 1 -0.011719 -0.35352 5 5 0 0 1 0.025391 -0.5 5 5 0 0 1 0.074219 -0.49414 5 5 0 0 1 0.12305 -0.48438 5 5 0 0 1 0.17188 -0.46875 5 5 0 0 1 0.2168 -0.44922 5 5 0 0 1 0.26172 -0.42578 5 5 0 0 1 0.30273 -0.39844 5 5 0 0 1 0.33984 -0.36523 5 5 0 0 1 0.37695 -0.33008 5 5 0 0 1 0.40625 -0.29102 5 5 0 0 1 0.43359 -0.24805 5 5 0 0 1 0.45508 -0.20508 5 5 0 0 1 0.47461 -0.1582 5 5 0 0 1 0.48828 -0.10938 5 5 0 0 1 0.49609 -0.060547 5 5 0 0 1 0.35352 -0.011719z"
|
||||
fill="#e0e0e0"
|
||||
id="path2" />
|
||||
<circle
|
||||
cx="8"
|
||||
cy="1044.4"
|
||||
r="3"
|
||||
fill="#fff"
|
||||
fill-opacity=".58824"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-opacity=".32549"
|
||||
stroke-width="3"
|
||||
id="circle4" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-0.06779632,-1036.4)"
|
||||
id="g18">
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:0.78430996;stroke-width:3;stroke-linejoin:round;stroke-opacity:0.39216003"
|
||||
cx="8"
|
||||
cy="1044.4"
|
||||
r="3"
|
||||
id="circle16" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 3.8 KiB |
@ -0,0 +1,193 @@
|
||||
#include "timer_sync.h"
|
||||
|
||||
void MainFrameTime::clamp_idle(float min_idle_step, float max_idle_step) {
|
||||
if (idle_step < min_idle_step) {
|
||||
idle_step = min_idle_step;
|
||||
} else if (idle_step > max_idle_step) {
|
||||
idle_step = max_idle_step;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
// returns the fraction of p_frame_slice required for the timer to overshoot
|
||||
// before advance_core considers changing the physics_steps return from
|
||||
// the typical values as defined by typical_physics_steps
|
||||
float MainTimerSync::get_physics_jitter_fix() {
|
||||
return Engine::get_singleton()->get_physics_jitter_fix();
|
||||
}
|
||||
|
||||
// gets our best bet for the average number of physics steps per render frame
|
||||
// return value: number of frames back this data is consistent
|
||||
int MainTimerSync::get_average_physics_steps(float &p_min, float &p_max) {
|
||||
p_min = typical_physics_steps[0];
|
||||
p_max = p_min + 1;
|
||||
|
||||
for (int i = 1; i < CONTROL_STEPS; ++i) {
|
||||
const float typical_lower = typical_physics_steps[i];
|
||||
const float current_min = typical_lower / (i + 1);
|
||||
if (current_min > p_max)
|
||||
return i; // bail out of further restrictions would void the interval
|
||||
else if (current_min > p_min)
|
||||
p_min = current_min;
|
||||
const float current_max = (typical_lower + 1) / (i + 1);
|
||||
if (current_max < p_min)
|
||||
return i;
|
||||
else if (current_max < p_max)
|
||||
p_max = current_max;
|
||||
}
|
||||
|
||||
return CONTROL_STEPS;
|
||||
}
|
||||
|
||||
// advance physics clock by p_idle_step, return appropriate number of steps to simulate
|
||||
MainFrameTime MainTimerSync::advance_core(float p_frame_slice, int p_iterations_per_second, float p_idle_step) {
|
||||
MainFrameTime ret;
|
||||
|
||||
ret.idle_step = p_idle_step;
|
||||
|
||||
// simple determination of number of physics iteration
|
||||
time_accum += ret.idle_step;
|
||||
ret.physics_steps = floor(time_accum * p_iterations_per_second);
|
||||
|
||||
int min_typical_steps = typical_physics_steps[0];
|
||||
int max_typical_steps = min_typical_steps + 1;
|
||||
|
||||
// given the past recorded steps and typcial steps to match, calculate bounds for this
|
||||
// step to be typical
|
||||
bool update_typical = false;
|
||||
|
||||
for (int i = 0; i < CONTROL_STEPS - 1; ++i) {
|
||||
int steps_left_to_match_typical = typical_physics_steps[i + 1] - accumulated_physics_steps[i];
|
||||
if (steps_left_to_match_typical > max_typical_steps ||
|
||||
steps_left_to_match_typical + 1 < min_typical_steps) {
|
||||
update_typical = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (steps_left_to_match_typical > min_typical_steps)
|
||||
min_typical_steps = steps_left_to_match_typical;
|
||||
if (steps_left_to_match_typical + 1 < max_typical_steps)
|
||||
max_typical_steps = steps_left_to_match_typical + 1;
|
||||
}
|
||||
|
||||
// try to keep it consistent with previous iterations
|
||||
if (ret.physics_steps < min_typical_steps) {
|
||||
const int max_possible_steps = floor((time_accum)*p_iterations_per_second + get_physics_jitter_fix());
|
||||
if (max_possible_steps < min_typical_steps) {
|
||||
ret.physics_steps = max_possible_steps;
|
||||
update_typical = true;
|
||||
} else {
|
||||
ret.physics_steps = min_typical_steps;
|
||||
}
|
||||
} else if (ret.physics_steps > max_typical_steps) {
|
||||
const int min_possible_steps = floor((time_accum)*p_iterations_per_second - get_physics_jitter_fix());
|
||||
if (min_possible_steps > max_typical_steps) {
|
||||
ret.physics_steps = min_possible_steps;
|
||||
update_typical = true;
|
||||
} else {
|
||||
ret.physics_steps = max_typical_steps;
|
||||
}
|
||||
}
|
||||
|
||||
time_accum -= ret.physics_steps * p_frame_slice;
|
||||
|
||||
// keep track of accumulated step counts
|
||||
for (int i = CONTROL_STEPS - 2; i >= 0; --i) {
|
||||
accumulated_physics_steps[i + 1] = accumulated_physics_steps[i] + ret.physics_steps;
|
||||
}
|
||||
accumulated_physics_steps[0] = ret.physics_steps;
|
||||
|
||||
if (update_typical) {
|
||||
for (int i = CONTROL_STEPS - 1; i >= 0; --i) {
|
||||
if (typical_physics_steps[i] > accumulated_physics_steps[i]) {
|
||||
typical_physics_steps[i] = accumulated_physics_steps[i];
|
||||
} else if (typical_physics_steps[i] < accumulated_physics_steps[i] - 1) {
|
||||
typical_physics_steps[i] = accumulated_physics_steps[i] - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// calls advance_core, keeps track of deficit it adds to animaption_step, make sure the deficit sum stays close to zero
|
||||
MainFrameTime MainTimerSync::advance_checked(float p_frame_slice, int p_iterations_per_second, float p_idle_step) {
|
||||
if (fixed_fps != -1)
|
||||
p_idle_step = 1.0 / fixed_fps;
|
||||
|
||||
// compensate for last deficit
|
||||
p_idle_step += time_deficit;
|
||||
|
||||
MainFrameTime ret = advance_core(p_frame_slice, p_iterations_per_second, p_idle_step);
|
||||
|
||||
// we will do some clamping on ret.idle_step and need to sync those changes to time_accum,
|
||||
// that's easiest if we just remember their fixed difference now
|
||||
const double idle_minus_accum = ret.idle_step - time_accum;
|
||||
|
||||
// first, least important clamping: keep ret.idle_step consistent with typical_physics_steps.
|
||||
// this smoothes out the idle steps and culls small but quick variations.
|
||||
{
|
||||
float min_average_physics_steps, max_average_physics_steps;
|
||||
int consistent_steps = get_average_physics_steps(min_average_physics_steps, max_average_physics_steps);
|
||||
if (consistent_steps > 3) {
|
||||
ret.clamp_idle(min_average_physics_steps * p_frame_slice, max_average_physics_steps * p_frame_slice);
|
||||
}
|
||||
}
|
||||
|
||||
// second clamping: keep abs(time_deficit) < jitter_fix * frame_slise
|
||||
float max_clock_deviation = get_physics_jitter_fix() * p_frame_slice;
|
||||
ret.clamp_idle(p_idle_step - max_clock_deviation, p_idle_step + max_clock_deviation);
|
||||
|
||||
// last clamping: make sure time_accum is between 0 and p_frame_slice for consistency between physics and idle
|
||||
ret.clamp_idle(idle_minus_accum, idle_minus_accum + p_frame_slice);
|
||||
|
||||
// restore time_accum
|
||||
time_accum = ret.idle_step - idle_minus_accum;
|
||||
|
||||
// track deficit
|
||||
time_deficit = p_idle_step - ret.idle_step;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// determine wall clock step since last iteration
|
||||
float MainTimerSync::get_cpu_idle_step() {
|
||||
uint64_t cpu_ticks_elapsed = current_cpu_ticks_usec - last_cpu_ticks_usec;
|
||||
last_cpu_ticks_usec = current_cpu_ticks_usec;
|
||||
|
||||
return cpu_ticks_elapsed / 1000000.0;
|
||||
}
|
||||
|
||||
MainTimerSync::MainTimerSync() :
|
||||
last_cpu_ticks_usec(0),
|
||||
current_cpu_ticks_usec(0),
|
||||
time_accum(0),
|
||||
time_deficit(0),
|
||||
fixed_fps(0) {
|
||||
for (int i = CONTROL_STEPS - 1; i >= 0; --i) {
|
||||
typical_physics_steps[i] = i;
|
||||
accumulated_physics_steps[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// start the clock
|
||||
void MainTimerSync::init(uint64_t p_cpu_ticks_usec) {
|
||||
current_cpu_ticks_usec = last_cpu_ticks_usec = p_cpu_ticks_usec;
|
||||
}
|
||||
|
||||
// set measured wall clock time
|
||||
void MainTimerSync::set_cpu_ticks_usec(uint64_t p_cpu_ticks_usec) {
|
||||
current_cpu_ticks_usec = p_cpu_ticks_usec;
|
||||
}
|
||||
|
||||
void MainTimerSync::set_fixed_fps(int p_fixed_fps) {
|
||||
fixed_fps = p_fixed_fps;
|
||||
}
|
||||
|
||||
// advance one frame, return timesteps to take
|
||||
MainFrameTime MainTimerSync::advance(float p_frame_slice, int p_iterations_per_second) {
|
||||
float cpu_idle_step = get_cpu_idle_step();
|
||||
|
||||
return advance_checked(p_frame_slice, p_iterations_per_second, cpu_idle_step);
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
#ifndef TIMER_SYNC_H
|
||||
#define TIMER_SYNC_H
|
||||
|
||||
#include "core/engine.h"
|
||||
|
||||
struct MainFrameTime {
|
||||
float idle_step; // time to advance idles for (argument to process())
|
||||
int physics_steps; // number of times to iterate the physics engine
|
||||
|
||||
void clamp_idle(float min_idle_step, float max_idle_step);
|
||||
};
|
||||
|
||||
class MainTimerSync {
|
||||
// wall clock time measured on the main thread
|
||||
uint64_t last_cpu_ticks_usec;
|
||||
uint64_t current_cpu_ticks_usec;
|
||||
|
||||
// logical game time since last physics timestep
|
||||
float time_accum;
|
||||
|
||||
// current difference between wall clock time and reported sum of idle_steps
|
||||
float time_deficit;
|
||||
|
||||
// number of frames back for keeping accumulated physics steps roughly constant.
|
||||
// value of 12 chosen because that is what is required to make 144 Hz monitors
|
||||
// behave well with 60 Hz physics updates. The only worse commonly available refresh
|
||||
// would be 85, requiring CONTROL_STEPS = 17.
|
||||
static const int CONTROL_STEPS = 12;
|
||||
|
||||
// sum of physics steps done over the last (i+1) frames
|
||||
int accumulated_physics_steps[CONTROL_STEPS];
|
||||
|
||||
// typical value for accumulated_physics_steps[i] is either this or this plus one
|
||||
int typical_physics_steps[CONTROL_STEPS];
|
||||
|
||||
int fixed_fps;
|
||||
|
||||
protected:
|
||||
// returns the fraction of p_frame_slice required for the timer to overshoot
|
||||
// before advance_core considers changing the physics_steps return from
|
||||
// the typical values as defined by typical_physics_steps
|
||||
float get_physics_jitter_fix();
|
||||
|
||||
// gets our best bet for the average number of physics steps per render frame
|
||||
// return value: number of frames back this data is consistent
|
||||
int get_average_physics_steps(float &p_min, float &p_max);
|
||||
|
||||
// advance physics clock by p_idle_step, return appropriate number of steps to simulate
|
||||
MainFrameTime advance_core(float p_frame_slice, int p_iterations_per_second, float p_idle_step);
|
||||
|
||||
// calls advance_core, keeps track of deficit it adds to animaption_step, make sure the deficit sum stays close to zero
|
||||
MainFrameTime advance_checked(float p_frame_slice, int p_iterations_per_second, float p_idle_step);
|
||||
|
||||
// determine wall clock step since last iteration
|
||||
float get_cpu_idle_step();
|
||||
|
||||
public:
|
||||
MainTimerSync();
|
||||
|
||||
// start the clock
|
||||
void init(uint64_t p_cpu_ticks_usec);
|
||||
// set measured wall clock time
|
||||
void set_cpu_ticks_usec(uint64_t p_cpu_ticks_usec);
|
||||
//set fixed fps
|
||||
void set_fixed_fps(int p_fixed_fps);
|
||||
|
||||
// advance one frame, return timesteps to take
|
||||
MainFrameTime advance(float p_frame_slice, int p_iterations_per_second);
|
||||
};
|
||||
|
||||
#endif // TIMER_SYNC_H
|
||||
Loading…
Reference in New Issue